【问题标题】:Posting to another model from a form in ASP.NET MVC从 ASP.NET MVC 中的表单发布到另一个模型
【发布时间】:2013-02-26 16:18:59
【问题描述】:

如果我有一个有模型的视图,可以说 Car..

@model Project.Car

在该视图中,我想创建一个将数据发送到新模型的表单

    @using (Html.BeginForm("Add", "Controller"))
    {
        @Html.Hidden("ID", "1")
        @Html.Hidden("UserID", "44")
        @Html.TextArea("Description")
    }

我注意到,如果我的操作是用我的 ViewModel 定义的,它就不起作用(模型始终为空):

    [HttpPost]
    public PartialViewResult Add(ViewModels.NewModel model)

但是,如果我使用 FormCollection,它可以工作:

    [HttpPost]
    public PartialViewResult Add(FormCollection formCollection)

这是视图模型:

public class NewModel
{
    public int ID { get; set; }
    public int UserID { get; set; }
    public string Description { get; set; }
}

我的问题是我可以从我的表单中将数据发布到 NewModel 吗?它所在的视图与 Project.Car 绑定是正确的。它是页面上的一个小表单,需要发布一组与 Project.Car 无关的不同数据。

【问题讨论】:

  • 你也可以发布 ViewModel 吗?
  • 但是您发布的是 Project.Car。不是吗?
  • 为什么你的ViewModel叫Add?那个对吗?

标签: c# asp.net asp.net-mvc razor


【解决方案1】:

是的,您可以将视图强输入到一个模型并将其发布到另一个模型。

这样做你有两个选择:

  1. 手动为每个输入字段提供正确的名称,以便默认活页夹能够理解并创建模型 (example)。

    虽然这可行,但这也意味着您必须注意拼写错误,并且如果您拼错属性名称,您将不会收到任何编译时错误。

  2. 在绑定到新模型类型的视图中手动创建 HTML 助手。然后它将为您正确生成 HTML。

    为了构造帮助程序,您需要一个包装器对象,该对象将以IViewDataContainer 接口的形式公开您的模型实例。您可以在任何地方定义该包装器,包括模型本身:

    public class NewModel
    {
      public int ID { get; set; }
      public int UserID { get; set; }
      public string Description { get; set; }
    
      public class WrapperForHtmlHelper : System.Web.Mvc.IViewDataContainer
      {
        public System.Web.Mvc.ViewDataDictionary ViewData { get; set; }
    
        public WrapperForHtmlHelper(NewModel value)
        {
            this.ViewData = new System.Web.Mvc.ViewDataDictionary<NewModel>(value);
        }
      }
    }
    

    然后在视图中创建一个绑定到NewModel 实例的助手:

    var ModelToPost = new YourApp.Models.NewModel() { ID = 1, UserID = 43, Description = "" }
    
    var hlp = new HtmlHelper<YourApp.Models.NewModel>
             (this.ViewContext,
              new YourApp.Models.NewModel.WrapperForHtmlHelper(ModelToPost)
             );
    

    然后你像往常一样使用帮助器:

    @hlp.HiddenFor(m => m.ID)
    @hlp.HiddenFor(m => m.UserID)
    @hlp.TextAreaFor(m => m.Description)
    

    那么您的PartialViewResult Add(ViewModels.NewModel model) 将正确接收数据。

【讨论】:

  • 我的朋友,我希望我能给你一大块肋骨来回答这个问题——太棒了。我把它做成通用的——因为你这里的代码太棒了。(看看这是否适合) public class ModelWrapper : System.Web.Mvc.IViewDataContainer 其中 T : 类 { public System.Web.Mvc.ViewDataDictionary ViewData { get;放; } public ModelWrapper(T value){this.ViewData = new System.Web.Mvc.ViewDataDictionary(value);} }
【解决方案2】:

您的模型名称与您的操作之间存在差异。在示例中,您显示的模型称为Add,而在您的操作中,您使用的是ViewModels.NewModel。更糟糕的是,您的视图被强类型化为一个名为Car 的模型。乱七八糟的。

所以从定义一个正确的视图模型开始:

public class CarViewModel
{
    public int ID { get; set; }
    public int UserID { get; set; }
    public string Description { get; set; }
}

然后是控制器:

public class CarsController: Controller
{
    public ActionResult Add()
    {
        var model = new CarViewModel
        {
            // don't ask me, those are the values you hardcoded in your view
            ID = 1,
            UserID = 44,
        };
        return View(model);
    }   

    [HttpPost]
    public PartialViewResult Add(CarViewModel model)
    {
        ...
    }
}

以及与您的视图模型对应的强类型视图:

@model CarViewModel
@using (Html.BeginForm())
{
    @Html.HiddenFor(x => x.ID)
    @Html.HiddenFor(x => x.UserID)
    @Html.TextAreaFor(x => x.Description)
    <button type="submit">Add</button>
}

【讨论】:

  • 我很抱歉,我在快速开发一项功能时发布了此信息,并且出于示例目的不得不更改操作和控制器的名称。我已经纠正了这个问题。
【解决方案3】:
My question is can I post data to NewModel from my form? 

简短的回答是肯定的,您可以将表单发布到与应用程序中的任何模型相关的任何控制器上的任何控制器操作。

例如,让您的表单发布到NewModel 控制器上的“Add”操作:

@using (Html.BeginForm("Add", "NewModel"))
    {
        @Html.Hidden("ID", "1")
        @Html.Hidden("UserID", "44")
        @Html.TextArea("Description")
    }

由于您的视图是强类型的 Car 模型,您可以更改此设置并将 ViewModel 发送到您的视图,其类型与您更新的模型匹配(如 Darin demonstrated),或者您需要映射将来自Car 的数据发布到控制器中的NewModel

关于CarControllerAdd 操作(发布):

[HttpPost]
public PartialViewResult Add(Car model)
{
    //now map attribute values from the Car model onto 
    //corresponding attributes of an instance of NewModel
    NewModel new = new NewModel();
    new.ID = model.ID;
    new.UserID = model.UserID;
    new.Desc = model.Description;
    //etc...

    //update your model/db
    _db.Add(new);

    //Redirect however you wish...
}

另外,请查看 AutoMapper,这是一个对象到对象映射器,它可以自动将 ViewModel 映射到模型,反之亦然。

【讨论】:

    【解决方案4】:

    您的视图设置为使用Project.Car 类型的模型然而您的操作方法采用ViewModels.NewModel 类型的模型,但也您的模型类已发布类型为Add

    将它们全部更改为匹配(假设Add 是正确的):

    查看:

    @model Add
    

    控制器:

    [HttpPost]
    public PartialViewResult Add(Add model)
    

    【讨论】:

      【解决方案5】:

      您也可以为此创建自定义模型绑定器。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-20
        • 2014-06-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多