4

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

Sheo Narayan
  • 1,196
  • 2
  • 14
  • 17
  • What does the request look like if you inspect it in your Network tab in your browsers developer tools? – Patrick Jul 07 '15 at 09:29
  • Data: IIS 8.0 Detailed Error - 404.0 - Not Found. Read the last part of my post above (Italic). – Sheo Narayan Jul 07 '15 at 09:33
  • Few links that might provide some useful information: http://stackoverflow.com/questions/14321988/http-put-not-allowed-in-asp-net-web-api http://stackoverflow.com/questions/15699950/requested-resource-does-not-support-http-method-put – Ric Jul 07 '15 at 10:06
  • Thanks Ric, however that is not the case now. ASP.NET MVC Web API allows HttpPut request type now as I have also mentioned in my post above and here is the example http://techfunda.com/Howto/angularjs/573/http-put-server-request This problem only comes when we are working with ASP.NET MVC controller. – Sheo Narayan Jul 07 '15 at 10:18
  • I meant what url is used when sending the request. I can see the error in your question text obviously. – Patrick Jul 07 '15 at 10:21
  • Remote Address:[::1]:2888 Request URL:http://localhost:2888/ServerRequest/PutDataResponse?firstName=fasd&lastName=fdas&age=5 Request Method:PUT Status Code:404 Not Found ///////////////////// This was the message from Developer toolbar (network tab). If I copy-paste this Requested url in the browser after removing [HttpGet] attribute from action method, this url works. This localhost url doesn't work directly from browser when action method has [HttpPut] obviously because browser sends get request. – Sheo Narayan Jul 07 '15 at 10:27

2 Answers2

3

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.

Sheo Narayan
  • 1,196
  • 2
  • 14
  • 17
0

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.

sarin
  • 5,227
  • 3
  • 34
  • 63
  • Thanks Sarin, I have only one HttpPut that is written in my code snippet above. I tried passing using querystring as well. I want to send $http.put not $http.get. The problem here is that it simply throws error in the client side itself. If it goes on server and I do not get data then it make sense but AngularJS is not able to send $http.put request on the mvc action method. As said, it works if I action method is ASP.NET MVC Web API. – Sheo Narayan Jul 07 '15 at 09:09
  • I suspect your routing is wrong. I.e the url your are requesting data from is different to the url of the mvc action method. Please post the contents your routing configuration file in your mvc app. Also, please confirm the actual request url being made either as above comment suggests in the network tab or using fiddler. – sarin Jul 07 '15 at 09:37
  • Sarin, I can confirm that the url requested is same as written in the $http.get. I have default RouteConfig, no change in the routeconfig file. When I remove [HttpPut] from PutDataResponse action method and directly request the url on in the browser it works. With [HttpPut] it will not work from the browser as the url by default sends [HttpGet] that is understood. I am wondering it is to do with some configurationt hat is stopping AngularJS send $http.put request to the server. – Sheo Narayan Jul 07 '15 at 09:45
  • Try changing it to an [HttpPost] and $http.post . See if that makes a difference – sarin Jul 07 '15 at 12:38
  • As written in my original post, $http.post and $http.get works fine. The problem comes in $http.put and $http.delete only. – Sheo Narayan Jul 07 '15 at 17:33