【问题标题】:How to sent ObjectViewModel from View to Controller in ASP.NET MVC C#?如何在 ASP.NET MVC C# 中将对象 ViewModel 从视图发送到控制器?
【发布时间】:2014-05-17 03:12:19
【问题描述】:

我正在使用 MVC 模板在 ASP.NET Web 应用程序中工作。

我正在尝试将 ObjectViewModel 从 View.cshtml 发送或传递给 Controller,但在 Controller 中,ObjectViewModel 以 null 形式到达。

思路如下: 我用 RegisterViewModel 类型的对象集合显示视图 IndexUsersInActiveDirectory.cshtml。在此视图中,有一个 @Html.ActionLink 用于将集合的元素发送到 Register 控制器:

IndexUsersInActiveDirectory.csthml

@model IEnumerable<SecureEscuelaWithIdentity.Models.RegisterViewModel>
@{
    ViewBag.Title = "IndexUsersInActiveDirectory";
}

<h2>IndexUsersInActiveDirectory</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
    <th>
        @Html.DisplayNameFor(model => model.UserName)
    </th>
    <th>
        @Html.DisplayNameFor(model => model.Email)
    </th>
    <th></th>
</tr>

@foreach (var item in Model) {
<tr>
    <td>
        @Html.DisplayFor(modelItem => item.UserName)
    </td>
    <td>
        @Html.DisplayFor(modelItem => item.Email)
    </td>
    <td>
        @Html.ActionLink("Select", "Register", new { item })
    </td>
</tr>
}
</table>

控制器寄存器是下一个:

//
// GET: /Account/Register
[Authorize(Roles = "Admin")]
public ActionResult Register(RegisterViewModel model)
{
    return View(model);
}

RegisterViewModel 类是:

public class RegisterViewModel
{
    [Required]
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [Required]
    [Display(Name = "Email")]
    public string Email { get; set; }
}

Register.cshtml 视图

    @model SecureEscuelaWithIdentity.Models.RegisterViewModel
@{
    ViewBag.Title = "Register";
}

<h2>@ViewBag.Title.</h2>

@using (Html.BeginForm("RegisterInApp", "Account", FormMethod.Post, new { @class =    "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    <h4>Create a new account.</h4>
    <hr />
    @Html.ValidationSummary()
    <li>@Html.ActionLink("ActiveDirectory", "IndexUsersInActiveDirectory", "Account")</li>
    <div class="form-group">
        @Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" class="btn btn-default" value="Register" />
        </div>
    </div>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

如何将整个集合元素(作为模型)发送到控制器?

【问题讨论】:

    标签: c# asp.net razor controller


    【解决方案1】:

    有2个问题

    1) 您在 ActionLink 的第 4 个参数上缺少一个空值

    @Html.ActionLink("Select", "Register", new { item }, null)
    

    如果没有第四个参数,它假定第三个参数是 HTML 属性而不是查询字符串参数。

    我发现第 4 个小参数“怪癖”是 MVC 中最烦人的覆盖之一。

    2) 您的item 需要是可以通过查询字符串传递的简单数据值

    由于您的项目不是简单的值类型,因此您需要传回其唯一值。例如:

    @Html.ActionLink("Select", "Register", new { name = item.Name, email = item.Email }, null)
    

    动作链接不做回发,它们只是在页面中创建锚链接,所以任何值都必须在查询字符串中传递。

    更改接收动作以匹配:

    [Authorize(Roles = "Admin")]
    public ActionResult Register(string name, string email)
    {
        RegisterViewModel model = new RegisterViewModel()
        {
             Name = name, 
             Email = email
        };
        return View(model);
    }
    

    但我把这些细节留给你:)

    【讨论】:

      【解决方案2】:

      TrueBlueAussie提出的方案适用于浏览器地址栏显示querystring没有问题的场景。

      如果是这样,@Html.ActionLink 可能是这样的:

      @Html.ActionLink("Select", "Register", new {item}, null) 
      

      因为控制器会将“item”作为 RegisterViewModel 对象(尽管实际上是一个查询字符串)。注意:不要忘记贡献 TrueBlueAussie "null" 的第四个参数。

      Register 控制器如下所示:

      [Authorize (Roles = "Admin")]
      public ActionResult Register (RegisterViewModel model) 
      { 
          return View (model); 
      } 
      

      有效!

      如上所述,这会在注册视图中显示查询字符串,这在我的实现中是不正确的。我不想在地址栏中显示此查询字符串。

      为了实现这一点,我添加了一个中间控制器,负责接收“项目”(来自 IndexUsersInActiveDirectory.csthml)作为 RegisterViewModel 对象(实际上它是一个查询字符串),并将这个对象添加到 TempData 字典中,并带有一个名为“模型”。

      这里是控制器RegisterTemp:

      [Authorize (Roles = "Admin")] 
      public ActionResult RegisterTemp (RegisterViewModel model) 
      { 
          TempData ["model"] = model; 
          return RedirectToAction ("Register"); 
      } 
      

              

      在“IndexUsersInActiveDirectory.csthml”视图中,@ActionLink 指向控制器 RegisterTemp 而不是控制器 Register,如下所示:

      @ Html.ActionLink ("Select", "RegisterTemp", new {item}, null) 
      

      重要的是,RegisterTemp 将“RedirectToAction”返回到 Register 视图。

      最后,当 RegisterTemp 控制器将 RedirectToAction 返回到 Register 控制器时,它会从 TempData 字典中获取带有“model”键的元素,以便将其返回给视图。因此,Register 控制器是:

      // 
      // GET: / Account / Register 
      [Authorize (Roles = "Admin")] 
      public ActionResult Register () 
      { 
          return View (TempData ["model"]); 
      } 
      

      我提到过,@TrueBlueAussie 提出的解决方案对于显示查询字符串并不重要的场景是完全可用的。

      我刚才详述的解决方案是避免显示该查询字符串。

      如果有更正确的解决方案来解决我的场景,欢迎。

      【讨论】:

        【解决方案3】:

        您必须使用“for”循环来迭代元素,如 for (int i; i

        所以收藏不会在发布时丢失。

        阅读本文了解更多详情: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/

        【讨论】:

        • 没有。在这个问题中,foreach 循环内没有编辑输入。问题在于 ActionLinks。
        猜你喜欢
        • 1970-01-01
        • 2018-11-25
        • 1970-01-01
        • 1970-01-01
        • 2021-12-26
        • 2014-03-07
        • 1970-01-01
        • 2021-09-15
        • 2021-01-04
        相关资源
        最近更新 更多