【问题标题】:ASP.NET MVC Passing models by ActionLinkASP.NET MVC 通过 ActionLink 传递模型
【发布时间】:2014-02-03 13:48:36
【问题描述】:

我想在单击ActionLink 时将模型和int 传递给控制器​​。

@Html.ActionLink("Next", "Lookup", "User", new { m = Model.UserLookupViewModel, page = Model.UserLookupViewModel.curPage }, null)

不起作用,而是传递模型的一个空白实例,这是使用new 时所期望的。

@Html.ActionLink("Next", "Lookup", "User", Model.UserLookupViewModel, null)

确实有效。

控制器

[HttpGet]
public ActionResult Lookup(UserLookupViewModel m, int page = 0)
{
    return this.DoLookup(m, page);
}

查看模型

public class UserLookupViewModel
{
    public int curPage { get; set; }

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

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

    [Display(Name = "DOB")]
    public DateTime? DoB { get; set; }

    [Display(Name = "Post code")]
    public string Postcode { get; set; }
}

如何将它们一起传递? Lookup 方法的参数与 ActionLink 中的命名属性匹配。

【问题讨论】:

  • 你不能使用 ActionLink 传递模型
  • MVC4 允许您通过 URL 变量自动传递模型,这是我的第二个示例。
  • ActionLink 的文档显示该方法的所有重载都不接受视图模型对象。 msdn.microsoft.com/en-us/library/… 您可以传递 RouteValues,根据您的第二个示例,但不能传递整个对象。
  • 假设视图模型的属性由页面上的控件填充,我只想发布一个表单,向我们展示您的剃须刀代码。
  • 为什么要使用 ActionLink 而不是发布表单?

标签: asp.net asp.net-mvc


【解决方案1】:

您不能使用 ActionLink 通过 Link 传递属性,但您可以执行以下操作来获得相同的行为。

<form action="/url/to/action" Method="GET">
  <input type="hidden" name="Property" value="hello,world" />
  <button type="submit">Go To User</button>
</form>

如果您创建一个助手来生成这些 GET 表单,您将能够像常规链接按钮一样设置它们的样式。我唯一要注意的是页面上的 ALL 表单很容易被修改,所以我不相信这些数据。当你到达你要去的地方时,我宁愿再次提取数据。

我在创建搜索操作时使用上述技术并希望保留搜索历史并保持后退按钮正常工作。

希望对你有帮助,

哈立德 :)


附言

这样做的原因。

@Html.ActionLink("Next", "Lookup", "User", Model.UserLookupViewModel, null)

是因为ActionLink方法的参数列表被泛化为取一个对象,所以什么都取。它将对该对象执行的操作是将其传递给 RouteValueDictionary,然后尝试根据该对象的属性创建一个查询字符串。

如果您说该方法在上面工作,您也可以尝试向视图模型添加一个名为 Id 的新属性,它会按照您的意愿工作。

【讨论】:

    【解决方案2】:

    您必须将模型序列化为 JSON 字符串,并将其发送到控制器以转换为对象。

    这是您的操作链接:

    @Html.ActionLink("Next", "Lookup", "User", new { JSONModel = Json.Encode(Model.UserLookupViewModel), page = Model.UserLookupViewModel.curPage }, null)
    

    在您的控制器中,您需要一种将 JSON 数据转换为 MemoryStream 的方法:

    private Stream GenerateStreamFromString(string s)
    {
      MemoryStream stream = new MemoryStream();
      StreamWriter writer = new StreamWriter(stream);
      writer.Write(s);
      writer.Flush();
      stream.Position = 0;
      return stream;
    }
    

    在 ActionResult 中,将 JSON 字符串转换为对象:

    public ActionResult YourAction(string JSONModel, int page)
    {
      DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Model.UserLookupViewModel));
      var yourobject =  (UserLookupViewModel)ser.ReadObject(GenerateStreamFromString(JSONModel));
    }
    

    【讨论】:

    • 当使用的语言无法显示时,请不要使用 sn-ps 进行格式化。它不会改善答案,并使您的答案更加混乱。常规代码块可以正常工作。
    【解决方案3】:

    虽然出于安全考虑,我强烈建议您使用表单来完成您在此处尝试执行的操作。

     @Html.ActionLink("Next", "Lookup", "User", new 
          { Forenames = Model.UserLookupViewModel.Forenames, 
            Surname = Model.UserLookupViewModel.Surname, 
            DOB = Model.UserLookupViewModel.DOB,  
            PostCode = Model.UserLookupViewModel.PostCode, 
            page = Model.UserLookupViewModel.curPage }, null)
    

    MVC 将适当地映射属性;但是,这将使用您的 url 将值传递给控制器​​。这将显示全世界都可以看到的值。

    出于安全考虑,我强烈建议使用表单,尤其是在处理 DOB 等敏感数据时。

    我个人会这样做:

     @using (Html.BeginForm("Lookup", "User")
     {
         @Html.HiddenFor(x => x.Forenames)
         @Html.HiddenFor(x => x.Surname)
         @Html.HiddenFor(x => x.DOB)
         @Html.HiddenFor(x => x.PostCode)
         @Html.HiddenFor(x => x.curPage)
    
         <input type="submit" value="Next" />
      }
    

    如果需要,您可以在页面上包含多个此类表单。

    然后你的控制器接受一个帖子,但功能相同:

     [HttpPost]
     public ActionResult Lookup(UserLookupViewModel m, int page = 0)
     {
         return this.DoLookup(m, page);
     }
    

    【讨论】:

    • 抱歉购买 HiddenFor 不安全。它仍然将数据发送到页面供用户查看,它在源中,只是在页面上不可见。
    • 如果没有“安全”说明,这个答案将很好地补充现有答案,因为它是唯一使用Html.BeginFormHtml.HiddenFor 的答案。
    【解决方案4】:

    请试试这个解决方案:

    @{
    var routeValueDictionary = new RouteValueDictionary("");
    routeValueDictionary.Add("Forenames",Forenames);
    routeValueDictionary.Add("Surname",Surname);
    routeValueDictionary.Add("DoB ",DoB );
    routeValueDictionary.Add("Postcode",Postcode );
    routeValueDictionary.Add("Page",PageNum );
    // Add any item you want!
    }
    @html.ActionLink("LinkName", "ActionName", "ControllerName",
    routeValueDictionary , new{@class="form-control"})
    

    【讨论】:

      猜你喜欢
      • 2016-10-18
      • 1970-01-01
      • 1970-01-01
      • 2013-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-16
      相关资源
      最近更新 更多