How do I enable HTTP PUT and DELETE for ASP.NET MVC in IIS?

[Origin]: http://stackoverflow.com/questions/12440277/how-do-i-enable-http-put-and-delete-for-asp-net-mvc-in-iis

Go to Handler Mappings in your IIS Manager. Find ExtensionlessUrlHandler-Integrated-4.0, double click it. Click Request Restrictions… button and on Verbs tab, add both DELETE and PUT. enter image description here


EDIT: Possible WebDav Publisher issue

You’ve mention on a deleted post you were running on a 2008 server right? Try removing webDav role, or disable it from your site config: on system.webServer -> modules section, remove WebDAVModule module:

<system.webServer>
  <modules>
    <remove name="WebDAVModule" />
  </modules>
  <handlers>
    <remove name="WebDAV" />
  </handlers>
</system.webServer>
shareedit
Advertisements

Asp.NET Web API – 405 – HTTP verb used to access this page is not allowed – how to set handler mappings

[Origin]: http://stackoverflow.com/questions/9854602/asp-net-web-api-405-http-verb-used-to-access-this-page-is-not-allowed-how

I wrote REST service using ASP.NET Web API. I’m trying to send HttpDelete request, however I get the following error:

405 - HTTP verb used to access this page is not allowed

I think I’m close to the solution, I found out that I should enable IIS remote management , go to Handler Mappings section and add DELETE verb to the appropriate position… but the problem is that there is a lots of different positions on the list… (sth like here: http://www.somacon.com/p126.php).

Which one should I edit? Few of them don’t have extension, e.g. “ExtensionUrlHandler-Integrated-4.0” and I added DELETE verb to it, but it still doesn’t work…

It was just a shot in the dark to modify that one, so should I modify different position? If so, which one? Or maybe is there anything more what I should do?

The same web service work perfectly fine on my local service, so I guess the problem is with the remote IIS…

Greetings

shareedit

Common cause for this error is WebDAV. Make sure you uninstall it.

shareedit

You don’t need to uninstall WebDAV, just add these lines to the web.config:

<system.webServer>
  <modules>
    <remove name="WebDAVModule" />
  </modules>
  <handlers>
    <remove name="WebDAV" />
  </handlers>
</system.webServer>
shareedit

Return either xml or json from MVC web api based on request

Given the following webapiconfig;

config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

and this controller;

public class ProductsController : ApiController
{
    Product[] _products = new Product[] 
    { 
        new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 }, 
        new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M }, 
        new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M } 
    };

    public IEnumerable<Product> GetAllProducts()
    {
        return _products;
    }
}

Using the URL http://localhost/api/Products I get a list of products in XML format.

What I would like to do is have the option to return either json or xml based on the request. So for json, it would be;

http://localhost/api/Products.json

and for XML, it would be;

http://localhost/api/Products.xml

likewise;

http://localhost/api/Products.json/1/
http://localhost/api/Products.xml/1/

Is this possible and how would I achieve this functionality?

An alternative would be something like;

http://localhost/api/json/Products/
shareedit

Yes you can achieve that with AddUriPathExtensionMapping

You can create routes like this:

routes.MapHttpRoute(
  name: "Api UriPathExtension",
  routeTemplate: "api/{controller}.{extension}/{id}",
  defaults: new { id = RouteParameter.Optional, extension = RouteParameter.Optional }
);

routes.MapHttpRoute(
  name: "Api UriPathExtension ID",
  routeTemplate: "api/{controller}/{id}.{extension}",
  defaults: new { id = RouteParameter.Optional, extension = RouteParameter.Optional }
); 

Then you need to extend the formatters:

  config.Formatters.JsonFormatter.AddUriPathExtensionMapping("json", "application/json");
  config.Formatters.XmlFormatter.AddUriPathExtensionMapping("xml", "text/xml");

Make sure to add reference to System.Net.Http.Formatting, as these methods are extension methods and intellisense won’t see them by default.

Remember in this example, you still have to issue the request with the appropriate content-type. However, if you want to have these directly available via the browser address bar you can map to “text/html”.

I wrote a blog post about all that a while ago – which should be helpful and take you into more details http://www.strathweb.com/2012/04/different-mediatypeformatters-for-same-mediaheadervalue-in-asp-net-web-api/

shareedit

WebAPI cannot parse multipart/form-data post

[Origin]: http://education-eco.blogspot.ca/2014/01/webapi-cannot-parse-multipartform-data.html

I’m trying to accept a post from a client (iOS app) and my code keeps failing on reading the stream. Says the message is not complete. I’ve been trying to get this working for hours it seems like something is wrong in my message format or something. All I’m trying to do is read a string but the developer I’m working with who is doing the iOS part only knows how to send multipart/form-data not content-type json.

Here is exact error: Unexpected end of MIME multipart stream. MIME multipart message is not complete.”

It fails here: await Request.Content.ReadAsMultipartAsync(provider);

Headers:

POST http://localhost:8603/api/login HTTP/1.1
Host: localhost:8603
Accept-Encoding: gzip,deflate
Content-Type: multipart/form-data; boundary=------------nx-oauth216807
Content-Length: 364
Accept-Language: en-us
Accept: */*
Connection: keep-alive

Body:

--------------nx-oauth216807
Content-Disposition: form-data; name="token"

CAAH5su8bZC1IBAC3Qk4aztKzisZCd2Muc3no4BqVUycnZAFSKuleRU7V9uZCbc8DZCedYQTIFKwJbVZCANJCs4ZCZA654PgA22Nei9KiIMLsGbZBaNQugouuLNafNqIOTs9wDvD61ZA6WSTd73AVtFp9tQ1PmFGz601apUGHSimYZCjLfGBo40EBQ5z6eSMNiFeSylym1pK4PCvI17fXCmOcRix4cs96EBl8ZA1opGKVuWizOsS0WZCMiVGvT
--------------nx-oauth216807

Here is the WebAPI code:

    public async Task&lt;HttpResponseMessage&gt; PostFormData()
    {
        // Check if the request contains multipart/form-data.
        if (!Request.Content.IsMimeMultipartContent())
        {
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
        }
        try
        {
        string root = HttpContext.Current.Server.MapPath("~/App_Data");
        var provider = new MultipartFormDataStreamProvider(root);

        // Read the form data and return an async task.
        await Request.Content.ReadAsMultipartAsync(provider);

        // This illustrates how to get the file names.
        foreach (MultipartFileData file in provider.FileData)
        {
            Trace.WriteLine(file.Headers.ContentDisposition.FileName);
            Trace.WriteLine("Server file path: " + file.LocalFileName);
        }
        return Request.CreateResponse(HttpStatusCode.OK);

        }
        catch (System.Exception e)
        {
            return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
        }
    }

A \r\n needs to be appended at the end of request content stream.

Instead of using this line to read the data: await Request.Content.ReadAsMultipartAsync(provider);

You will need to:
1. load the request stream to memory
2. append the \r\n string that is required
3. create a stream content from the memory content
4. manually add the request headers to the stream content
5. Finally use this instead: streamContent.ReadAsMultipartAsync(provider);

Check the answer of Landuber Kassa here for the complete code: http://stackoverflow.com/questions/13770536/asp-net-web-api-unexpected-end-of-mime-multi-part-stream-when-uploading-from-fl/17290999#comment42617381_17290999

Modify the Request Queue Limit, requestQueueLimit or Queue Length in IIS 7

[Origin]: https://blogs.msdn.microsoft.com/benjaminperkins/2011/11/14/modify-the-request-queue-limit-requestqueuelimit-or-queue-length-in-iis-7/

November 14, 2011

When optimizing and tuning an ASP.NET application you may want to increase the value of the requestQueueLimit.  The requestQueueLimit is the maximum number of requests that can be queued by an ASP.NET process before errors get returned to the client.

Modify Request Queue Limit within the Aspnet.config

Below, the requestQueueLimit is configured in the Aspnet.config file for a 64 bit version of the .NET 4 Framework.  The Aspnet.config exists by default, for 64bit .Net 4, in the following directory:

C:\Windows\Microsoft.NET\Framework64\v4.0.30319

Adding the applicationPool element to the Aspnet.config, as shown in Figure 1, for the given .NET version means that all application pools running on IIS 7 in Integrated mode using this version of the .NET framework will be impacted by the modification.

Figure 1, settings for the applicationPool element.

Modify Queue Length for a given Application Pool

Below, shown in Figure 2, the Queue Length is configured from the Advanced Settings of a specific Application Pool.

Figure 2, settings for the application pool

The Queue Length is the maximum number of requests that will be queued, when exceeded new requests will receive a 503 “Service Unavailable” response.

Conclusion

In most cases the default configuration will work best, therefore only make modifications when you are certain of the need and impact.

“The type or namespace name ‘Route’ could not be found” using “attribute routing”

[Origin]: http://stackoverflow.com/questions/24419324/the-type-or-namespace-name-route-could-not-be-found-using-attribute-routing

Just trying to splice some code from one working project to another. The “from” project uses “attribute routing” where you embed [Route(…)] directives in the Web API controller modules to indicate what HTTP message should route to what service routine.

Works fine in the “from” project, but in the “to” project I get the build error “The type or namespace name ‘Route’ could not be found (are you missing a using directive or an assembly reference?)”

I’ve tried copying essentially all of the using statements from the “from” project to the “to” project, but that has no apparent effect. None of the MS documentation suggests that a NuGet package is required (or even a using statement). Both projects are supposedly ASP.NET MVC 4.

(And, yes, I updated WebApiConfig.cs with the config.MapHttpAttributeRoutes(); statement.)

Any ideas??

shareedit

This comment from Vedran Mandić solved the problem for me. I’m re-posting it here because I think it should be the answer (or at least a answer).

I did an ‘Update-Package Microsoft.AspNet.WebApi.WebHost -reinstall’ and it worked. Funny this happens after getting the latest version on different PCs from TFS. I guess this happens because of nuget packages not working properly with the versioning system

shareedit

Optional parameters in ASP.NET Web API

[Originally Posted By]: http://stackoverflow.com/questions/11862069/optional-parameters-in-asp-net-web-api

I need to implement the following WebAPI method:

/api/books?author=XXX&amp;title=XXX&amp;isbn=XXX&amp;somethingelse=XXX&amp;date=XXX

All of the parameters can be null, i.e. the caller can specify from 0 to all the 5 parameters.

In MVC4 beta I used to do the following:

public class BooksController : ApiController
{
    // GET /api/books?author=tolk&amp;title=lord&amp;isbn=91&amp;somethingelse=ABC&amp;date=1970-01-01
    public string GetFindBooks(string author, string title, string isbn, string somethingelse, DateTime? date) 
    {
        // ...
    }
}

MVC4 RC doesn’t behave like this anymore. If I specify less than 5 parameters, it replies with a 404saying

No action was found on the controller ‘Books’ that matches the request.

What is the correct method signature to make it behave like it used to, without having to specify the optional parameter in the URL routing?

shareedit

This issue has been fixed in the regular release of MVC4. Now you can do:

public string GetFindBooks(string author="", string title="", string isbn="", string  somethingelse="", DateTime? date= null) 
{
    // ...
}

and everything will work out of the box.

shareedit