Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No HTTP resource error when doing PUT/POST [CORS issue - AngularJS + Web API 2]

There are so many questions in SO similar to this, but none have fixed my issue.

I've have an angularjs website hosted at http://localhost:49595 and I'm calling a Web Api 2.1 service hosted at http://localhost:63019. I've enabled CORS on the web api server in web.config. Requests for GET /buildings/1 and GET /buildings/?$top=10&$skip=1 work fine.

When it comes to PUT, I get the following error: { "Message":"No HTTP resource was found that matches the request URI 'http://localhost:63019/buildings/1105'.", "MessageDetail":"No action was found on the controller 'Building' that matches the request." }

Error in chrome

I can see the browser sends the OPTIONS request to the server, but the actual data to be updated is not in the request (checked in fiddler. Not sure if this is normal for an OPTIONS query.

enter image description here

I enabled tracing on the web api, and I see the following log. https://gist.github.com/rnarayana/8905229 The OPTIONS request (line 69) says it needs to do a PUT. Around line 77, it looks like it picked the correct action. And then the controller gets disposed. Moreover the controller is getting instantiated twice.

How can I find out what is happening?

Calling code in AngularJS: Tried:

$http.put('http://localhost:63019/buildings/' + building.BuildingId, building)
.then(onSuccess, onError);

also

$http({
    url: urlBase + '/' + building.BuildingId,
    dataType: 'json',
    method: 'PUT',
    data: building,
    headers: {"Content-Type": "application/json"}
}).then(onSuccess, onError);

These are in my controller:

[HttpGet]
[Route("buildings/")]
public IHttpActionResult GetAll(ODataQueryOptions<BuildingViewModel> queryOptions)
{
}

[HttpGet]
[Route("buildings/{id}")]
public IHttpActionResult Get(long id)
{
}

[Route("buildings/")]
[HttpPost]
public IHttpActionResult Post(BuildingEditViewModel buildingEditViewModel)
{
}

[HttpPut]
[Route("buildings/{id}")]
public IHttpActionResult Put(long id, [FromBody]BuildingEditViewModel buildingEditViewModel)
{
}

//Added this as per some blog. Not helping.
[HttpOptions]
[Route("buildings/{id}")]
public HttpResponseMessage Options(long id)
{
    var response = new HttpResponseMessage();
    response.StatusCode = HttpStatusCode.OK;
    return response;
}

My webapi web.config has:

<system.webServer>
        <modules runAllManagedModulesForAllRequests="true">
          <remove name="WebDAVModule" />
        </modules>
        <handlers>
          <remove name="WebDAV" />
          <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>
        <httpProtocol>
          <customHeaders>
            <add name="Access-Control-Allow-Origin" value="http://localhost:49595" />
            <add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS, PUT, DELETE" />
            <add name="Access-Control-Allow-Headers" value="*" />
          </customHeaders>
        </httpProtocol>
    </system.webServer>

My WebApiConfig.Register() has:

public static void Register(HttpConfiguration config)
    {
    config.EnableSystemDiagnosticsTracing();
    config.Services.Replace(typeof(ITraceWriter), new WebApiTracer());

    //Enable CORS. The allowed origins and verbs are in the config file. Do not add in both places.
    config.EnableCors();

    // Attribute routing.
    config.MapHttpAttributeRoutes();

    config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(
        config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault((t => t.MediaType == "application/xml")));
}
like image 509
Narayana Avatar asked Feb 09 '14 21:02

Narayana


2 Answers

I had issues getting it to work with the the values in the config so I removed them from there and I added the following to my WebApiConfig class:

        //Specify values as appropriate (origins,headers,methods)
        var cors = new EnableCorsAttribute("http://myurl","*","*");
        config.EnableCors(cors);

You can find the nuget package for Microsoft ASP.NET Web API 2.2 Cross-Origin from here

like image 88
link64 Avatar answered Oct 03 '22 08:10

link64


Besides the config option config.EnableCors(); in your Register method you need to enable CORS in your controller by using [EnableCors] attribute along with the declaration of the controller, here is an example how I do it:

 [EnableCors(origins: "http://localhost:49595", headers: "*", methods: "*")]
 public class ValuesController : ApiController
 {
 ...
like image 30
Dalorzo Avatar answered Oct 03 '22 06:10

Dalorzo