Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Model Binding Issue with ASP.NET5 MVC6

Im trying to post some JSON data on an angular form to my ASP.NET5 MVC6 Controller action. The model binder does not seem to be working. Not sure what I'm missing here.

My ASP Controller:

public class DefaultController : Controller
{
    public IActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public IActionResult SubmitTest(QTestViewModel model)
    {
        return Json("true");
    }
}

My Angular Controller:

angular.module("testActiveMq", [])
.controller("MqTestController", ["$scope", "$http", function ($scope, $http) {
    // Submit Form
    $scope.submitForm = function () {
        debugger;
        var formData = (this.data) ? angular.toJson(this.data) : null;
        if (formData && this.qForm && this.qForm.$valid) {
            $http({
                url: "/Default/SubmitTest",
                data: formData,
                method: "POST",
                dataType: "json",
                contentType: "application/json; charset=utf-8"
            })
            .then(function successCallback(response) {
                debugger;
                // this callback will be called asynchronously
                // when the response is available
            }, function errorCallback(response) {
                debugger;
                // called asynchronously if an error occurs
                // or server returns response with an error status.
            });
        }
    };
}])

My View Model:

public class QTestViewModel
{
    public string MqBrokerUri { get; set; }

    public string ClientId { get; set; }

    public string UserName { get; set; }

    public string Password { get; set; }

    public int TotalRequests { get; set; }

    public int MaxConcurrentRequests { get; set; }

    public int DelayBetweenThreads { get; set; }
}

When I make a request, the HTTP Headers are ..

POST /Default/SubmitTest HTTP/1.1
Host: localhost:50877
Connection: keep-alive
Content-Length: 225
Accept: application/json, text/plain, */*
Origin: http://localhost:50877
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36
Content-Type: application/json;charset=UTF-8
Referer: http://localhost:50877/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8

My form data looks like so ..

{"MqBrokerUri":"ssl://broker-uri:1616?transport.acceptInvalidBrokerCert=true","ClientId":"MqLoadTest","UserName":"myunm","Password":"mypwd","TotalRequests":100,"MaxConcurrentRequests":10,"DelayBetweenThreads":1}

I feel like I'm missing something super obvious. Why is my JSON data not binding to my model? Surely I dont need a custom model binder for something so simple?

like image 903
Rohit L Avatar asked Dec 04 '15 04:12

Rohit L


2 Answers

Your code was enough in MVC 5 and earlier versions to receive the model in your controller. However in MVC 6 you also need to set the [FromBody] parameter in your controller action:

[HttpPost]
public IActionResult SubmitTest([FromBody]QTestViewModel model)
{
    return Json("true");
}

Not sure why this is a requirement in MVC 6, but your model will keep its default values if you dont add the FromBody attribute.

  • Check for example the Web API tutorial in the official docs.

  • After some digging into the source, it seems the BodyModelBinder will only accept models that specifically enabled the body binding source, which is done adding the [FromBody] attribute.

    var allowedBindingSource = bindingContext.BindingSource;
    if (allowedBindingSource == null ||
        !allowedBindingSource.CanAcceptDataFrom(BindingSource.Body))
    {
        // Formatters are opt-in. This model either didn't specify [FromBody] or specified something
        // incompatible so let other binders run.
        return ModelBindingResult.NoResultAsync;
    }
    

PS. Angular is stringifying by default the json objects, but if in case you use something like jQuery you also need to manually call JSON.stringify.

like image 68
Daniel J.G. Avatar answered Oct 29 '22 09:10

Daniel J.G.


Sometime it's happened with json better to use it

var jsonResult=json("true");
jsonResult.maxJsonLength=int32.maxValue
return jsonresult;

Hope it will help for you.

like image 25
Pankaj Gupta Avatar answered Oct 29 '22 07:10

Pankaj Gupta