private bool TryGetLock(string fileId, out LockInfo lockInfo)
		{
			//TODO: This lock implementation is not thread safe and not persisted and all in all just an example.
			if (Locks.TryGetValue(fileId, out lockInfo))
			{
				if (lockInfo.Expired)
				{
					Locks.Remove(fileId);
					return false;
				}
				return true;
			}

			return false;
		}
		public async Task<IActionResult> PerformAction(string id, [FromQuery]string access_token)
		{
			var editSession = await GetEditSessionAsync(id);
			string wopiOverrideHeader = HttpContext.Request.Headers[WopiHeaders.WopiOverride];

			//TODO: Replace the else-ifs with separate methods (https://github.com/petrsvihlik/WopiHost/issues/7)
			// http://stackoverflow.com/questions/39302121/header-based-routing-in-asp-net-core

			if (wopiOverrideHeader.Equals("COBALT"))
			{
				var responseAction = editSession.SetFileContent(await HttpContext.Request.Body.ReadBytesAsync());

				HttpContext.Response.Headers.Add(WopiHeaders.CorrelationId, HttpContext.Request.Headers[WopiHeaders.CorrelationId]);
				HttpContext.Response.Headers.Add("request-id", HttpContext.Request.Headers[WopiHeaders.CorrelationId]);

				return new Results.FileResult(responseAction, "application/octet-stream");
			}
			else if (wopiOverrideHeader.Equals("LOCK") || wopiOverrideHeader.Equals("UNLOCK") || wopiOverrideHeader.Equals("REFRESH_LOCK") || wopiOverrideHeader.Equals("GET_LOCK"))
			{
				string oldLock = Request.Headers[WopiHeaders.OldLock];
				string newLock = Request.Headers[WopiHeaders.Lock];

				LockInfo existingLock = null;
				bool lockAcquired = TryGetLock(id, out existingLock);
				lock (Locks)
				{
					switch (wopiOverrideHeader)
					{
						case "GET_LOCK":
							break;

						case "LOCK":
							if (oldLock != null)
							{
								if (lockAcquired)
								{
									if (existingLock.Lock == oldLock)
									{
										// Replace the existing lock with the new one
										Locks[id] = new LockInfo { DateCreated = DateTime.UtcNow, Lock = newLock };
										Response.Headers[WopiHeaders.OldLock] = newLock;
										return new OkResult();
									}
									else
									{
										// The existing lock doesn't match the requested one.  Return a lock mismatch error along with the current lock
										return ReturnLockMismatch(Response, existingLock.Lock);
									}
								}
								else
								{
									// The requested lock does not exist.  That's also a lock mismatch error.
									return ReturnLockMismatch(Response, reason: "File not locked");
								}
							}
							else
							{
								if (lockAcquired)
								{
									// There is a valid existing lock on the file
									return ReturnLockMismatch(Response, existingLock.Lock);
								}
								else
								{
									// The file is not currently locked, create and store new lock information
									Locks[id] = new LockInfo { DateCreated = DateTime.UtcNow, Lock = newLock };
									return new OkResult();
								}
							}

						case "UNLOCK":
							if (lockAcquired)
							{
								if (existingLock.Lock == newLock)
								{
									// Remove valid lock
									Locks.Remove(id);
									return new OkResult();
								}
								else
								{
									// The existing lock doesn't match the requested one.  Return a lock mismatch error along with the current lock
									return ReturnLockMismatch(Response, existingLock.Lock);
								}
							}
							else
							{
								// The requested lock does not exist.
								return ReturnLockMismatch(Response, reason: "File not locked");
							}

						case "REFRESH_LOCK":
							if (lockAcquired)
							{
								if (existingLock.Lock == newLock)
								{
									// Extend the lock timeout
									existingLock.DateCreated = DateTime.UtcNow;
									return new OkResult();
								}
								else
								{
									// The existing lock doesn't match the requested one. Return a lock mismatch error along with the current lock
									return ReturnLockMismatch(Response, existingLock.Lock);
								}
							}
							else
							{
								// The requested lock does not exist.  That's also a lock mismatch error.
								return ReturnLockMismatch(Response, reason: "File not locked");
							}
					}
				}

				return new OkResult();
			}
			else
			{
				// Unsupported action
				return new NotImplementedResult();
			}
		}