Sheo Narayan
Sheo Narayan

Reputation: 1206

AngularJS $http.put doesn't work with ASP.NET MVC controller

I am trying to create simple page where I am sending some data to the server using $http.put.

Script code

<script>
var myApp = angular.module("myApp", []);
myApp.controller("HttpPostController", function ($scope, $http) {

    $scope.SendHttpPostData = function () {

        var data = $.param({
            firstName: $scope.firstName,
            lastName: $scope.lastName,
            age : $scope.age
        });

        $http.put('/ServerRequest/PutDataResponse', data)
        .success(function (data, status, headers, config) {
            $scope.ServerResponse = data;
        })
        .error(function (data, status, header, config) {
            $scope.ServerResponse =  htmlDecode("Data: " + data +
                "\n\n\n\nstatus: " + status +
                "\n\n\n\nheaders: " + header +
                "\n\n\n\nconfig: " + config);
        });
    };

});</script>

My HTML code

<div ng-app="myApp" ng-controller="HttpPostController">
<form ng-submit="SendHttpPostData()">
    <p>First Name: <input type="text" name="firstName" ng-model="firstName" required /></p>
    <p>Last Name: <input type="text" name="lastName" ng-model="lastName" required /></p>
    <p>Age : <input type="number" name="age" ng-model="age" required /></p>
    <input type="submit" value="Submit" />
    <hr />
    {{ ServerResponse }}
</form></div>

ASP.NET MVC controller action method

    [HttpPut]
    public ContentResult PutDataResponse(string firstName, string lastName, int age)
    {
        return Content("First name: " + firstName +
            " | Last name: " + lastName +
            " | Age: " + age +
            " | Request Type: " + Request.RequestType.ToString());
    }

The error message I get is following

TTP Error 404.0 - Not Found The resource you are looking for has been removed, had its name changed, or is temporarily unavailable. Most likely causes: The directory or file specified does not exist on the Web server. The URL contains a typographical error. A custom filter or module, such as URLScan, restricts access to the file. Things you can try: Create the content on the Web server. Review the browser URL. Check the failed request tracing log and see which module is calling SetStatus.

So in ASP.NET MVC it doesn't work. (POST and GET works). I tried the above with ASP.NET MVC Web API and it works fine. I am able to send and receive response using PUT method of mvc web api.

The question is why it doesn't work in ASP.NET MVC even if the method verb is [HttpPut].

Thanks

Upvotes: 4

Views: 1682

Answers (2)

Sheo Narayan
Sheo Narayan

Reputation: 1206

Okay, after much effort I found the solution. Actually, the problem was that by default ASP.NET MVC doesn't allow "PUT" or "DELETE" request type so we need to enable them in the web.config file like below.

  <system.webServer>
<modules>
  <remove name="FormsAuthentication" />
  <remove name="FormsAuthenticationModule" />
</modules>
<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>
  </system.webServer>

Notice the ExtensionlessUrlHandler-Integrated-4.0 handler. This makes the difference. This is allowing all types of verb acceptable and so even PUT request now works with ASP.NET MVC.

Upvotes: 3

sarin
sarin

Reputation: 5307

I suspect the model binding works differently. You are passing in :

    var data = $.param({
        firstName: $scope.firstName,
        lastName: $scope.lastName,
        age : $scope.age
    });

An object with 3 properties. Yet your MVC controller method is looking for 3 parameters only: string firstName, string lastName, int age

You could change your MSC controller method to expect an object with 3 properties i.e:

public class myViewModel
{
    string firstName; 
    string lastName;
    int age;
}

public ContentResult PutDataResponse(myViewModel formData)

or

Change the request to pass the parameters in the URL:

$http.get('/ServerRequest/PutDataResponse?firstname=bob&lastname=smith&age=12')

Also, check your route : '/ServerRequest/PutDataResponse' . If you are using default routing, This will map to Your /ServerRequestController and the first HttpPut method. From your example I don't know if you have more than one HttpPut method on your controller. If you do, you could add an attribute route [Route("ServerRequest/PutDataResponse")] to the top of your MVC method.

Upvotes: 0

Related Questions