Html.BeginForm 传递模型项值

Posted

技术标签:

【中文标题】Html.BeginForm 传递模型项值【英文标题】:Html.BeginForm passing Model item value 【发布时间】:2014-07-14 01:18:08 【问题描述】:

我正在使用 mvc4 并正在使用 html.BeginForm 在我的视图中调用另一个控制器

它工作正常!但这里使用文本框来传递值。 如何修改此代码,所以我正在使用

@Html.DisplayFor(modelItem => item.UserName) ....代替 @Html.TextBox("用户名")

这是我的看法:

图片:

                     @using OTMS.Models
        @model IEnumerable<OTMS.Models.UserProfile>

        @
           ViewBag.Title = "Index";
        

                <!-- Table Continer -->
        <div class="spacer_10px"></div>
        <div class="container clearfix">
            <div class="grid_12"> 
               <div class="table_wrapper table_gray">
        <table>

             <tr>
                <th>
                   <p>User Name</p>
                </th>
                 <th>
                   <p>Role</p>
                </th>
                 <th>
                   <p>Role</p>
                </th>
            </tr>


            @if (Model != null) 
        foreach (var item in Model) 
        <tr>


            <td>
                @Html.DisplayFor(modelItem => item.UserName)
            </td>

            <td>
              @using(Html.BeginForm("GetRoles", "Account",FormMethod.Post))
              @Html.AntiForgeryToken()
            <div class="editor-label">Username : </div>
             @Html.TextBox("UserName") //here user will enter user name / I dont want user to enter that ,it should be done Automatically 



                  <div class="spacer_20px"></div>
                  <div class="button button-orange"> <span class=" form_button clearfix">
                  <input type="submit" class="submit" name="submit" value="Get Roles for this User" />
                  </span> </div>//by clicking that will pass the user name to controller (GerRole)/I dont want  button
        


            </td>

            <td>

               @using (Html.BeginForm("Submit", "Account", FormMethod.Post))
           
                     @Html.Hidden("userName", item.UserName)

                     @Html.DropDownList("selectedRole", (SelectList)ViewBag.Roles)

                     <div class="button button-orange"> <span class=" form_button clearfix">
                    <input type="submit" class="submit" name="submit" value="Update Change" />
                    </span> </div>
            

            </td>
        </tr>

        
            
             </table>
                 </div> </div> 

这里是我的控制器:

   public ActionResult Index()
    
        var model = _db.UserProfiles.ToList();

        ViewBag.Roles = new SelectList(Roles.GetAllRoles());

        return View(model);
    

    [HttpPost]

    public ActionResult GetRoles(string UserName)
    
        if (!string.IsNullOrWhiteSpace(UserName))
        
            ViewBag.RolesForThisUser = Roles.GetRolesForUser(UserName);
            SelectList list = new SelectList(Roles.GetAllRoles());
            ViewBag.Roles = list;


        
        return View("showrole");
    

另一种观点:

它的图像:

            @
                ViewBag.Title = "showrole";
            

            <h2>showrole</h2>
            @if(ViewBag.RolesForThisUser != null) 
                <text>
                <h3>Roles for this user </h3>
                <ol>
            @foreach (string s in ViewBag.RolesForThisUser)
                <li>@s</li>   
            
                            </ol>
                </text>
            

【问题讨论】:

为什么要使用@Html.DisplayFor?为什么不@Html.EditorFor? 我只想显示值..没有输入字段和提交按钮.. 我不清楚你想归档什么。您想要调用另一个控制器的表单,但您不想要提交按钮,但是您打算如何将数据发布到控制器?或者带有@Html.DisplayFor(modelItem => item.UserName) 的代码不起作用,您想知道如何正确使用它? 没有代码工作 再次看到 Q 我更新它。我使用提交按钮转到另一个视图 ..我不希望我想在表格和相同的视图中显示它们,我不知道怎么样! 看来我了解您要归档的内容。基本上你想摆脱这个用户按钮的获取角色,只让第三列工作。当您使用 _db.UserProfiles.ToList() 进行查询时,重要的是要知道您在 UserProfile 中是否具有当前用户的一个或多个角色? 【参考方案1】:

你需要做的是为你的视图创建一个视图模型,对我来说它看起来像这样:

public class UserViewModel

    public string UserName get;set;
    public IEnumerable<string> UserRoles  get; set; 

然后在您的索引操作中,您将返回这些视图模型的列表。 你当然可以这样做:

public ActionResult Index()

    var model = _db.UserProfiles.ToList()
                                .Select(u => new UserViewModel
                                     UserName = u.UserName,
                                     UserRoles = Roles.GetRolesForUser(u.UserName)
                                                      .AsEnumerable()
                                )
                                .ToList();
    ViewBag.Roles = new SelectList(Roles.GetAllRoles());
    return View(model);

但我不会。这是因为使用此代码,您正在为每个用户执行一个附加查询,只是为了获取他的角色。我认为您需要将角色表添加到您的 EntityFramework 模型中,并尝试使用单个查询来执行此操作。因此,您需要使用角色扩展您的 UserProfile:

[Table("UserProfile")]
public class UserProfile

    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId  get; set; 
    public string UserName  get; set; 

    public ICollection<UserRoles> UserRoles  get; set; 


[Table("webpages_Roles")]
public class UserRoles

    [Key]
    public int RoleId  get; set; 
    public string RoleName  get; set; 

    public ICollection<UserProfile> UserProfiles  get; set; 

然后使用有关 UserProfils 和 UserRoles 之间多对多关系的信息更新您的 DbContext:

public class UsersContext : DbContext

    public UsersContext()
        : base("DefaultConnection")
    
    

    public DbSet<UserProfile> UserProfiles  get; set; 

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    
        modelBuilder.Entity<UserRoles>()
        .HasMany<UserProfile>(r => r.UserProfiles)
        .WithMany(u => u.UserRoles)
        .Map(m =>
        
            m.ToTable("webpages_UsersInRoles");
            m.MapLeftKey("UserId");
            m.MapRightKey("RoleId");
        );
    

在您的索引操作之后 - 您可以简单地执行以下操作:

    var model = _db.UserProfiles.Select(u => new UserViewModel()
    
        UserName = u.UserName,
        UserRoles = u.UserRoles.Select(ur=>ur.RoleName)
    ).ToList();

这将是一个查询而不是循环中的几个。

编辑: 您的模型已更改,因此您需要将 @model IEnumerable&lt;OTMS.Models.UserProfile&gt; 更改为 @model IEnumerable&lt;OTMS.Models.UserViewModel&gt; 然后:

@foreach(var user in Model)

    //display user
    @foreach(var role in user.UserRoles)
    
        //display roles with @role
    

如果您想使用 DisplayTemplates - 您可以将显示用户的逻辑移动到模板中。为此,您需要按路径创建视图 ~/Views/Shared/DisplayTemplates/UserViewModel.cshtml

@model OTMS.Models.UserViewModel
//display user
@foreach(var role in user.UserRoles)

     //display roles with @role

然后在 Index.cshtml 中您可以将代码更改为:

@foreach (var user in Model)

    @Html.DisplayFor(n => user)

【讨论】:

先向您介绍解决方案。那么我如何在视图中呈现角色? 更新了我的答案。请参阅编辑部分中的更改。 Oleksii Aza 非常感谢,谢谢..我做了第一个解决方案:) ......你今天才知道我真的知道(viewModel)的用途。所以它使用当我想组合 2 个表时对吗? 一般来说 ViewModel 是你的视图的骨架。它可以是 2 个表的组合,但有时它可以从一个表中获取数据并调整它以供查看。例如:如果您需要仅包含用户名的页面 - 您不必将整个 IEnumerable 放在视图上。更好的解决方案是创建 ViewModel,其中包含 IEnumerable 和项目用户名。 好的。我在第三列中的提交按钮的另一个 Q 正在更改用户角色,我可以在我的数据库中看到更改,但是我单击它会刷新页面(但表格将为空!)。我的代码:公共 ActionResult 提交(string userName, string selectedRole) //我的逻辑返回 View("Index"); 【参考方案2】:

首先,主要的困惑在于这个助手..看看这里

当您想要提供用户不需要注意的发布数据时,请使用 HiddenFor。"

当您想显示记录但不允许对其进行编辑时,请使用 DisplayFor

当您希望允许用户输入或允许用户编辑字段时,请使用 TextBoxFor。 `

现在你的问题是这样的.. How can i use displayfor to hit my controller!!!!

您可以使用 HiddenFor 和 DisplayFor 组合来完成此操作。使用 HiddenFor 让值准备好发布,并使用 DisplayFor 显示这些值。

为了满足您的要求

<div class="editor-label"> Username : </div>
@Html.TextBox("UserName") 

替换

<div class="editor-label"> Username : </div>
@Html.HiddenFor(modelItem=>item.username)
@Html.DisplayFor(modelItem=>item.username) 

记住Displayfor在浏览器中仅呈现标签,要将其发布回控制器,您需要HiddenFor

【讨论】:

这不是调用我发布的控制器! 变量不匹配..将变量编辑为控制器中指定的变量 我的意思是我在控制器中的参数是字符串 UserName..在哪里把它放在我的视图中? 我更新它 Q .am 使用提交按钮转到另一个视图..我不希望我想在表格和同一个视图中显示它们,我不知道如何!【参考方案3】:

试试这个:

控制器

[HttpPost]
public ActionResult GetRoles(string UserName)

    if (!string.IsNullOrWhiteSpace(UserName))
    
        ViewBag.RolesForThisUser = Roles.GetRolesForUser(UserName);
        SelectList list = new SelectList(Roles.GetAllRoles());
        ViewBag.Roles = list;
    
    return View("......");

查看

@ViewBag.Name
@using(Html.BeginForm("GetRoles", "Account"))
@Html.AntiForgeryToken()
<div class="editor-label">Username : </div>
@Html.TextBox("UserName")
<div class="spacer_20px"></div>
<div class="button button-orange">
    <span class=" form_button clearfix">
        <input type="submit" class="submit" name="submit" value="Get Roles for this User" />
    </span>
</div>

这里是 DEMO

【讨论】:

我只想显示值..没有输入字段和提交按钮..并通过调用控制器.. 你是什么意思,你需要像 this 这样的东西吗? 再次查看 Q 我更新它。我正在使用提交按钮转到另一个视图 ..我不想在表格和相同视图中显示它们,我不知道怎么样!

以上是关于Html.BeginForm 传递模型项值的主要内容,如果未能解决你的问题,请参考以下文章

MVC4 不会将模型传递给控制器

ASP.Net MVC 5 Html.BeginForm onsubmit 和具有所需属性的模型

单个视图中的多个表单

使用 javascript 将路由值传递给 Html.BeginForm

如何防止查询字符串但在 Html.BeginForm (GET) 中使用路由?

遵循MVVM模式,如何创建“设置”功能,在其他用户控件中设置数据绑定项值?