【问题标题】:MVC3 Html.BeginForm inside a WebGrid column?WebGrid 列中的 MVC3 Html.BeginForm?
【发布时间】:2012-09-26 15:34:44
【问题描述】:

今晚早些时候我有一个有点疯狂的想法,并且完成了 3/4 的实现方法并遇到了一个奇怪的问题。我想在控制器上自动生成所有方法的索引而不是返回 ActionResult ,以及每个人提交有效数据的简单表格。通过反射似乎是一件非常简单的事情:

Quickie ViewModel 来保存每个反射动作:

public class ReflectedAction
{
    public ReflectedAction(MethodInfo methodInfo, string controllerName)
    {
        this.ActionName = methodInfo.Name;
        this.ControllerName = controllerName;
        this.Parameters = methodInfo.GetParameters().Select(p => p.Name);
    }

    public string ControllerName { get; set; }

    public string ActionName { get; set; }

    public IEnumerable<string> Parameters { get; set; }
}

Action 反映当前控制器上的所有动作:

public virtual ActionResult AutoIndex()
{
    Type controllerType = this.ControllerContext.Controller.GetType();
    string controllerName = controllerType.Name.Replace("Controller", string.Empty);

    var methods = this.ControllerContext.Controller.GetType().GetMethods().Where(
            m => m.ReturnType.Name.Contains("ActionResult"));

    var model = methods.Select(m => new ReflectedAction(m, controllerName));

    return View(model);
}

在视图内部,我只想使用一个简单的 WebGrid 将每个动作呈现为一行,第一列是动作的名称,第二列是一个迷你表单,可以填充删除该操作具有的任何字段(我尝试将其作为帮助程序,或以网格格式内联,后者包含在此处:

@using TfsMvc.Controllers
@model IEnumerable<TestController.ReflectedAction>

@{
    ViewBag.Title = "AutoIndex";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>AutoIndex</h2>

@{
    var grid = new WebGrid(
        source: Model,
        ajaxUpdateContainerId: "grid",
        defaultSort: "ActionName",
        canPage: false);
}

<div id="grid">
    @grid.GetHtml(
    tableStyle: "grid",
    headerStyle: "head",
    alternatingRowStyle: "alt",
    columns: grid.Columns(
        grid.Column("ActionName"),
        grid.Column(format: (action) =>
            {
                using (Html.BeginForm((string)action.ActionName, (string)action.ControllerName, FormMethod.Get))
                {
                    string htmlString = string.Empty;

                    foreach (string parameter in action.Parameters)
                    {
                        htmlString = "<span>" + Html.Label(parameter) + Html.TextBox(parameter) + "</span>";
                    }

                    htmlString += "<input type=\"submit\" />";

                    return new HtmlString(htmlString);
                }
            }))
        )
</div>

网格出现可以正确呈现,但奇怪的是所有表单html标签都呈现在网格之外,而控件却呈现在网格内部:

<div id="grid">
    <form action="/Test/CloneTestPlan" method="get"></form>
    <form action="/Test/ConfigureTestPlan" method="get"></form>
    <form action="/Test/EnvConfig" method="get"></form>
    <form action="/Test/FixTestLink" method="get"></form>

    <!-- ton of other actions snipped-->

    <table class="grid">
        <thead>
            <tr class="head"><th scope="col"><a href="#" onclick="$(&#39;#grid&#39;).load(&#39;/Test/SecretIndex?sort=ActionName&amp;sortdir=DESC&amp;__=634581349851993336 #grid&#39;);">ActionName</a></th><th scope="col"></th></tr>
        </thead>
        <tbody>
            <tr><td>CloneTestPlan</td><td><span><label for="subid">subid</label><input id="subid" name="subid" type="text" value="" /></span><input type="submit" /></td></tr>
            <tr class="alt"><td>ConfigureTestPlan</td><td><span><label for="apply">apply</label><input id="apply" name="apply" type="text" value="" /></span><input type="submit" /></td></tr>
            <tr><td>EnvConfig</td><td><span><label for="create">create</label><input id="create" name="create" type="text" value="" /></span><input type="submit" /></td></tr>
            <tr class="alt"><td>FixTestLink</td><td><span><label for="commit">commit</label><input id="commit" name="commit" type="text" value="" /></span><input type="submit" /></td></tr>

            <!-- ton of other actions snipped-->

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

如您所见,标签呈现在表格的外部!知道我在这里做错了什么吗?或者您可以不 Webgrid 中的 BeginForm 吗?有没有更好的方法来制作一堆单独的表格?

提前致谢!

【问题讨论】:

  • 这真的很有趣。你用这个做什么?您是否使用它向您的开发团队展示功能?
  • 抱歉回复晚了,没看到你添加了评论。实际上主要是我懒惰而不是手动制作静态索引。 :) 我做了很多动作,但我不一定记得它们的名称或它们需要的确切参数。它们的名字通常很合理,所以我通常可以猜到……但是有一个自动生成的索引来显示它们要干净得多。

标签: asp.net-mvc-3 webgrid


【解决方案1】:

尝试自己渲染&lt;form&gt;,而不使用帮助器。

看起来 lambda 在它吐出内容之前在助手内部执行,这导致 BeginForm 立即呈现到输出。

【讨论】:

  • 啊哈!这至少可以解释这种奇怪的行为!手动渲染
    确实 does 工作,但它只是感觉很脏,意味着我也必须担心手动正确渲染路径。我真的很想有某种更清洁的方式来做到这一点。知道是否有办法强制助手在我期望的时间在 lambda 内执行?这似乎是 MVC 中的一个错误,如果不是..
  • 您仍然可以使用UrlHelper 来呈现网址。您也可以尝试在不使用using 指令的情况下调用Html.BeginFormHtml.EndForm。或者想出自己的扩展方法。
【解决方案2】:

我不确定它是否会对你的情况有所帮助,但我遇到了类似的问题,我所做的是:

  1. 使用以下代码创建部分

    @using(Html.BeginForm()){
        //some code
    }
    
  2. 在发生问题的地方,调用这个部分,所以在你的情况下它会是这样的:

    grid.Column(format: (action) =>
    {
        Html.Partial("SomePartial")
    })
    

PS:我调用 Partial 的地方不同,所以我不确定上面是否可行。

【讨论】:

    猜你喜欢
    • 2018-04-01
    • 2014-02-05
    • 2012-09-18
    • 2012-02-18
    • 1970-01-01
    • 2011-07-20
    • 1970-01-01
    • 1970-01-01
    • 2011-11-09
    相关资源
    最近更新 更多