Проблема с привязкой к модели с ASP.NET5 MVC6

Я пытаюсь опубликовать некоторые данные JSON в форме angular для моего действия MVC6-контроллера ASP.NET5. Модельное связующее, похоже, не работает. Не уверен, что мне здесь не хватает.

Мой ASP-контроллер:

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

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

My angular Контроллер:

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.
            });
        }
    };
}])

Моя модель просмотра:

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; }
}

Когда я делаю запрос, заголовки HTTP...

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

Мои данные формы выглядят так.

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

Я чувствую, что мне не хватает чего-то сверх очевидного. Почему данные JSON не привязаны к моей модели? Наверняка мне не нужен специальный связующий элемент для чего-то такого простого?

Ответ 1

Ваш код был достаточно в MVC 5 и более ранних версиях для получения модели в вашем контроллере. Однако в MVC 6 вам также необходимо установить параметр [FromBody] в действие вашего контроллера:

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

Не уверен, почему это требование в MVC 6, но ваша модель сохранит свои значения по умолчанию, если вы не добавите атрибут FromBody.

  • Проверьте, например, руководство по веб-API в официальных документах.

  • После некоторого копания в источнике кажется, что BodyModelBinder будет принимать только модели, которые специально активировали привязку body который добавлен атрибут [FromBody].

    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 строит по умолчанию объекты json, но если вы используете что-то вроде jQuery, вам также нужно вручную вызвать JSON.stringify.

Ответ 2

Когда-нибудь это случилось с json, чтобы использовать его

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

Надеюсь, это поможет вам.

Ответ 3

[edit] Похоже, этот ответ неверен. Моя проблема была вызвана тем, что параметр Action назван таким же, как одно из свойств объекта. Это привело к тому, что MVC использовал префикс для предотвращения неоднозначности. Я не согласен с тем, что это неоднозначно, и я обсуждаю это на Github.


Я только что зарегистрировал ошибку в Github об этом. Кажется, что если ваш параметр не назван CamelCase типа параметра, он ожидает, что поля в полезной нагрузке будут иметь префикс имени параметра.

Вы можете исправить это, добавив [Bind (Prefix = "")] перед параметром Action. public IActionResult SubmitTest([Bind(Prefix="")]QTestViewModel model)

Ответ 4

Ok @Daniel J.G. ответ не работал у меня Мне пришлось использовать [FromForm] вместо [FromBody] Чтобы заставить работать binging

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