【问题标题】:How do I add route values to hyperlink?如何将路由值添加到超链接?
【发布时间】:2015-11-28 10:14:00
【问题描述】:

使用VS2013,MVC5,假设一个模型有一个master/header记录,以及多个相关的detail,MVC view会在文本框中显示header数据,并在web grid中显示detail。控制器有一个 action 方法,它接受要显示的标头记录的 id。没有带有空参数列表的操作方法。当我单击结果/显示视图的 Web 网格标题超链接时,我收到一个错误...

参数字典包含参数“Id”的空条目 方法的不可空类型“System.Int32” 'System.Web.Mvc.ActionResult 索引(Int32)' 在 'WebGridTest.Controllers.HomeController'。可选参数必须 是引用类型、可为空的类型或被声明为可选项 范围。参数名称:参数

这是我的代码...

代码

型号

我的详细信息

namespace WebGridTest.Models
{
    public class MyDetail
    {
        public string Column1 { get; set; }
        public string Column2 { get; set; }
        public string Column3 { get; set; }
    }
}

我的标题

using System.Collections.Generic;

namespace WebGridTest.Models
{
    public class MyHeader
    {
        public MyHeader()
        {
            this.MyDetails = new List<MyDetail>();
        }

        public int Id { get; set; }
        public List<MyDetail> MyDetails { get; set; }
    }
}

控制器

HomeController

using System.Web.Mvc;

namespace WebGridTest.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index(int Id)
        {
            var model = new Models.MyHeader();
            model.Id = 2; // HARD CODED VALUES FOR DEMONSTRATING THIS ISSUE

            var detail1 = new Models.MyDetail();
            detail1.Column1 = "1A";
            detail1.Column2 = "1B";
            detail1.Column3 = "1C";
            model.MyDetails.Add(detail1);

            var detail2 = new Models.MyDetail();
            detail2.Column1 = "2A";
            detail2.Column2 = "2B";
            detail2.Column3 = "2C";
            model.MyDetails.Add(detail2);

            var detail3 = new Models.MyDetail();
            detail3.Column1 = "3A";
            detail3.Column2 = "3B";
            detail3.Column3 = "3C";
            model.MyDetails.Add(detail3);

            return View(viewName: "Index", model: model);
        }
    }
}

观看次数

Index.cshtml

@model WebGridTest.Models.MyHeader

@{
    ViewBag.Title = "Home Page";
}

@using (Html.BeginForm(actionName: "Index", controllerName: "Home", method: FormMethod.Post))
{
    <p></p>
    @Html.TextBoxFor(x => x.Id)
    <p></p>
    WebGrid grid = new WebGrid(null, canPage: false);
    grid.Bind(Model.MyDetails);

    @grid.GetHtml(tableStyle: "table table-bordered lookup-table", columns:
        grid.Columns(
            grid.Column(
                "Column1"
                , "Column 1"
                , (item) => (item.Column1)
            )
            ,
            grid.Column(
                "Column2"
                , "Column 2"
                , (item) => (item.Column2)
            )
            ,
            grid.Column(
                "Column3"
                , "Column 3"
                , (item) => (item.Column3)
            )
        )
    )
}

当我运行项目时,我收到上述错误。如果我从操作方法“索引”中删除参数,程序将不会产生错误。

当我将鼠标悬停在网页的标题上时,我会看到生成的 URL。我可以看到它不包括查询字符串参数列表中的路由值。它仅包括排序值。示例...

http://localhost:62802/Home/Index?sort=Column1&sortdir=ASC

我的例子是做作的和琐碎的,但我只想说,我需要 Id 来识别要显示的记录。

如何在列标题上指定 id 路由值?

【问题讨论】:

    标签: c# asp.net-mvc webgrid


    【解决方案1】:

    根据网络研究,许多开发人员建议使用 JavaScript 修改 DOM 以包含路由值。这似乎可行,但确实远离 MVC 结构,转而支持客户端评估和操作。信息在 IIS/MVC 中可用,但缺乏应用信息(特别是 Web 网格标题锚点)的能力。

    我找到了一个 JavaScript 的替代方案,它使解决方案完全使用 C#。我将以问答方式回答我自己的问题。

    解决方案涉及创建一个扩展方法,该方法将在响应原始客户端请求之前将路由值注入到生成的 HTML 中。这需要添加扩展方法类,并在视图中添加方法调用。

    示例...

    扩展方法类

    using System.Web;
    
    namespace WebGridTest
    {
        public static class ExtensionMethods
        {
            public static IHtmlString AddRouteValuesToWebGridHeaders(this IHtmlString grid, string routeValues)
            {
                var regularString = grid.ToString();
                regularString = regularString.Replace("?sort=", "?" + routeValues + "&sort=");
    
                HtmlString htmlString = new HtmlString(regularString);
    
                return htmlString;
            }
        }
    }
    

    增强视图

    (注意对扩展方法“AddRouteValuesToWebGridHeaders”的调用)...

    @model WebGridTest.Models.MyHeader
    
    @{
        ViewBag.Title = "Home Page";
    }
    
    @using (Html.BeginForm(actionName: "Index", controllerName: "Home", method: FormMethod.Post))
    {
        <p></p>
        @Html.TextBoxFor(x => x.Id)
        <p></p>
        WebGrid grid = new WebGrid(null, canPage: false);
        grid.Bind(Model.MyDetails);
    
        @grid.GetHtml(tableStyle: "table table-bordered lookup-table", columns:
            grid.Columns(
                grid.Column(
                    "Column1"
                    , "Column 1"
                    , (item) => (item.Column1)
                )
                ,
                grid.Column(
                    "Column2"
                    , "Column 2"
                    , (item) => (item.Column2)
                )
                ,
                grid.Column(
                    "Column3"
                    , "Column 3"
                    , (item) => (item.Column3)
                )
            )
        ).AddRouteValuesToWebGridHeaders("Id=" + Model.Id.ToString())
    }
    

    结论

    注入 HTML 不是首选解决方案,因为与任何其他解析算法一样,它是高度假设性的。我发现除了 HTML 解析之外别无他法。也许下载此类的 Microsoft 开源版本并创建具有所需行为的覆盖将是一个更优雅的解决方案。

    ** 请求 ** - Microsoft - 请在 Web 网格标题渲染中添加控制/增强锚点的功能。

    欢迎评论...

    【讨论】:

      猜你喜欢
      • 2020-02-14
      • 2017-10-12
      • 2021-01-27
      • 2018-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多