如何将路由值添加到超链接?

时间:2015-09-02 18:56:18

标签: c# asp.net-mvc webgrid

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

  

参数字典包含参数' Id'的空条目。的   非可空类型&System; Int32'方法   ' System.Web.Mvc.ActionResult Index(Int32)'在   ' WebGridTest.Controllers.HomeController&#39 ;.必须有一个可选参数   是引用类型,可空类型,或声明为可选   参数。参数名称:参数

这是我的代码......

代码

模型

MyDetail

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

MyHeader

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)
            )
        )
    )
}

当我运行项目时,我收到上述错误。如果我从动作方法中删除参数&#39;索引&#39;程序不会生成错误。

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

  

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

我的例子既人为又琐碎,但足以说明,我需要Id来识别要显示的记录。

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

1 个答案:

答案 0 :(得分:0)

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

我找到了JavaScript的替代方案,将解决方案完全保留在C#中。我将回答我自己的问题作为Q&amp; A风格的问题。

解决方案涉及创建一个扩展方法,该方法会在响应原始客户端请求之前将路由值注入生成的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;
        }
    }
}

增强视图

(请注意对扩展方法的调用&#39; AddRouteValuesToWebGridHeaders&#39;)...

@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网格标题呈现中控制/扩充锚点的功能。

请随时发表评论......