Reputation: 2599
When i send a put to my Api i first get method OPTIONS and an error. It then hits my select action method again and it contains the put info.
public HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
{
var request = controllerContext.Request;
if (request.IsInspectRequest())
{
var simulate = new ActionSelectSimulator();
request.Properties[RequestHelper.ActionCache] = simulate.Simulate(controllerContext);
}
var selectedAction = _innerSelector.SelectAction(controllerContext);
return selectedAction;
}
I have a class that handles my preflight request.
public class XHttpMethodOverrideHandler : DelegatingHandler
{
static readonly string[] httpOverrideMethods = { "PUT", "DELETE" };
static readonly string[] accessControlAllowMethods = { "POST", "PUT", "DELETE" };
static readonly string httpMethodOverrideHeader = "X-HTTP-Method-Override";
static readonly string ORIGIN_HEADER = "ORIGIN";
static readonly string accessControlAllowOriginHeader = "Access-Control-Allow-Origin";
static readonly string accessControlAllowMethodsHeader = "Access-Control-Allow-Methods";
static readonly string accessControlAllowHeadersHeader = "Access-Control-Allow-Headers";
protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
try
{
if (request.Method == HttpMethod.Post && request.Headers.Contains(httpMethodOverrideHeader))
{
var httpMethod = request.Headers.GetValues(httpMethodOverrideHeader).FirstOrDefault();
if (httpOverrideMethods.Contains(httpMethod, StringComparer.InvariantCultureIgnoreCase))
request.Method = new HttpMethod(httpMethod);
}
var httpResponseMessage = base.SendAsync(request, cancellationToken);
if (request.Method == HttpMethod.Options && request.Headers.Contains(ORIGIN_HEADER))
{
httpResponseMessage.Result.Headers.Add(accessControlAllowOriginHeader, request.Headers.GetValues(ORIGIN_HEADER).FirstOrDefault());
httpResponseMessage.Result.Headers.Add(accessControlAllowMethodsHeader, String.Join(", ", accessControlAllowMethods));
httpResponseMessage.Result.Headers.Add(accessControlAllowHeadersHeader, httpMethodOverrideHeader);
httpResponseMessage.Result.StatusCode = HttpStatusCode.OK;
}
else if (request.Headers.Contains(ORIGIN_HEADER))
httpResponseMessage.Result.Headers.Add(accessControlAllowOriginHeader, request.Headers.GetValues(ORIGIN_HEADER).FirstOrDefault());
return httpResponseMessage;
}
catch (Exception ex)
{
ILoggerService logger = IocContainer.Container.TryGetInstance<ILoggerService>();
if (logger != null)
{
logger.Error(ex);
}
return Task.FromResult<HttpResponseMessage>(request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex));
}
I also have added to my webconfig
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
When i send my Put Ajax call i receive an error. It hits my method and performs my action but it sends an error. If i send the put request via postman then i have no problem. If i send it from the client I get an error because the first method it gets is {OPTIONS}. What am i missing? Here is my Ajax put
$.ajax({
url: "http://localhost:61148/api/mycontroller",
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
async: true,
type: "PUT",
data: sendData,
datatype: 'json',
crossDomain: true,
success: function () {
Upvotes: 1
Views: 177
Reputation: 2599
I found the answer in a couple of other questions. The solution is so simple it hurts. If you're having this issue add an options method in your controller.
public HttpResponseMessage Options()
{
var response = new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK
};
return response;
}
Upvotes: 1