Публикация данных, когда моя модель представления имеет конструктор, не работает - PullRequest
10 голосов
/ 23 февраля 2012

У меня есть следующий код:

[HttpGet]
public ActionResult Edit(int req)
{
    var viewModel = new  EditViewModel();
    viewModel.RequestId = int;
    return View(viewModel);
}

[HttpPost]
Public ActionResult Edit(EditViewModel viewModel)
{
// some code here...
}

Работает нормально: при публикации формы редактирования у меня вызывается контроллер действий.

Теперь я немного изменил свой код следующим образом:

[HttpGet]
public ActionResult Edit(int req)
{
    var viewModel = new  EditViewModel(req);
    return View(viewModel);
}

[HttpPost]
Public ActionResult Edit(EditViewModel viewModel)
{
// some code here...
}

public class EditViewModel()
{
    public EditViewModel(int req)
    {
        requestId = req; 
    }
    ...
}

В этой новой версии у меня есть модель представления с конструктором.

На этот раз, когда моя форма отправляется обратно, контроллер действий никогда не запускается.

Есть идеи?

Спасибо.

Ответы [ 2 ]

18 голосов
/ 23 февраля 2012

Это нормально. Связыватель модели по умолчанию больше не может создавать экземпляр вашей модели представления, так как он не имеет конструктора без параметров. Вам нужно будет написать пользовательский механизм связывания моделей, если вы хотите использовать модели представлений, у которых нет конструктора по умолчанию.

Обычно вам не нужен такой пользовательский конструктор. Вы могли бы просто иметь свою модель вида так:

public class EditViewModel()
{
    public int RequestId { get; set; }
}

и подобное действие POST:

[HttpPost]
public ActionResult Edit(EditViewModel viewModel)
{
    // some code here...
}

и теперь все, что вам нужно сделать, это POST параметр requestId вместо req, и связыватель модели по умолчанию выполнит эту работу.

И если по какой-то причине вы хотели использовать модель представления с настраиваемым конструктором, вот пример того, как может выглядеть привязка настраиваемой модели:

public class EditViewModelBinder : DefaultModelBinder
{
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        var req = bindingContext.ValueProvider.GetValue("req");
        if (req == null)
        {
            throw new Exception("missing req parameter");
        }
        int reqValue;
        if (!int.TryParse(req.AttemptedValue, out reqValue))
        {
            throw new Exception(string.Format("The req parameter contains an invalid value: {0}", req.AttemptedValue));
        }

        return new EditViewModel(reqValue);
    }
}

который будет зарегистрирован в вашем Application_Start:

ModelBinders.Binders.Add(typeof(EditViewModel), new EditViewModelBinder());
0 голосов
/ 04 июня 2018

Asp.Net Core версия

public class EditViewModelBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)
        {
            throw new ArgumentNullException(nameof(bindingContext));
        }

        var req = bindingContext.ValueProvider.GetValue("req");
        if (req == ValueProviderResult.None || string.IsNullOrEmpty(req.FirstValue))
        {
            bindingContext.ModelState.TryAddModelError("req", "Missing req parameter");
        }

        int reqValue;
        if (!int.TryParse(req.AttemptedValue, out reqValue))
        {
            bindingContext.ModelState.TryAddModelError($"The req parameter contains an invalid value: {req.AttemptedValue}");
        }

        var model = new EditViewModel(req.FirstValue);

        bindingContext.Result = ModelBindingResult.Success(model);
        return Task.CompletedTask;
    }
}

Вам больше не нужно ничего регистрировать в startup.cs.Просто назначьте привязку вашей модели представления, и вы в отъезде.

[ModelBinder(BinderType = typeof(EditViewModelBinder))]
public class EditViewModel
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...