代码之家  ›  专栏  ›  技术社区  ›  Simon_Weaver

POST方法调用MVC用户控件及其父视图

  •  3
  • Simon_Weaver  · 技术社区  · 16 年前

    重写: 我最初的帖子似乎被误解了。此后,我将其报告为错误,并给出了以下描述。我关于这个问题的原始帖子可以在第二条下方找到 <HR >。


    我对用户控件中的POST有一个主要问题。

    • 我有一个UserControl,它有一个控制器,包含两个名为“ContactForm”的ActionMethod。第二个是ActionVerb。POST以回复帖子。用户控件主要通过AJAX使用,但这在这里实际上无关紧要。显然,这些操作方法呈现了一个局部视图。

    • 我有一个主页,其中包含“EnterContest”的额外html表单。同样,它的控制器有两个名为“EnterContest”的ActionMethod,其中一个响应ActionVerb。帖子。此视图在侧栏中包含“ContactForm”,其呈现方式为:

      <% Html.RenderAction("ContactUsForm", "Company", new { commentsBoxHeader = "Questions" }); %>

    回发“EnterContest”表单(视图上的主表单)时会出现问题。

    来自Fiddler的POST请求仅包含此查询字符串(显然不包含来自contact us表单的任何POST数据,因为这是一个完全独立的HTTP操作)。

    contestId=ND09&电子邮件=fred&btnEnterContest=提交

    (是的,这看起来像是GET,但那是 Fiddler在POST时也会显示什么)

    • 首先(如预期的那样),在主控制器中调用“EnterContest(FormCollection数据)”方法。这将处理表单提交以进入比赛-调用Web服务等。。

    • 第二-(非预期)-调用“ContactForm”控制器的POST方法。这会立即崩溃,因为它缺少预期的参数,而且我们不希望它被调用。这发生在同一个Http请求期间。

    如果我查看堆栈跟踪——它是从动态生成的aspx页面调用的——源自Html。上面显示的RenderAction代码行。因此,很明显,正在发生的事情是,希望部分呈现“ContactUs”操作方法的代码查看Request,发现有一个处理POST的方法,因此它将其路由到那里——这非常糟糕。它可能在框架中的某个地方:

    System.Web.Mvc.dll!System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod
    

    这种行为非常令人困惑,真的打破了看似简单的页面。我很确定这是一个bug——因为如果不在控制器中进行一些非常笨拙的检查,我就看不到一个优雅的解决方案。我认为RenderAction在未来会出现,但我不知道这个问题是存在于那里还是存在于主框架中。

    只是为了澄清没有发生的事情:

    • 任何聪明的jQuery
    • 多个HTTP请求(在Fiddler中验证)
    • 嵌套表单

    谢谢


    原始帖子

    我正在使用 RenderAction ASP.NET中的Html扩展名。NET MVC。

    我遇到了一些意想不到的事情,但仔细想想,这更有意义。

    假设我有一个包含“RenderAction”方法的视图,用于为页面的一部分生成联系人。

    <% Html.RenderAction("ContactUsForm", "Company", 
       new { commentsBoxHeader = "Questions" }); %>
    

    在这种情况下,它生成的部分视图创建了一个ajax表单,该表单通过以下方式发布 <%= Html.BeginAjaxForm() %> .

    因此,我当然需要一个actionresult来处理AJAX回发。

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult ContactUsForm(FormCollection formdata)
    

    现在,当 父视图 包含此部分呈现操作的表单是带有POST操作的普通(非ajax)表单。发生的事情是,POST方法 ContactUsForm 除了主视图的POST操作之外,action也是调用。在这个行动中 formdata 属性包含父视图的所有属性,因此 联系我们表格 以空引用或类似的方式死亡。

    我提出了三种可能的解决方案:

    1) 为页面上的任何用户控件的回发创建不同的操作名称。这有一个缺点,那就是你必须发布回与创建局部视图不同的函数。这通常会更麻烦,但这就是我现在正在做的。

    2) 检查每个POST方法(您必须记住在每个用户控件的POST操作方法中运行此检查),以查看表单数据是否针对该表单,如果不是,则返回默认视图。

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResultContactUsForm(FormCollection formData)
        {
            if (formData["btnSubmitContactUsForm"] == null) {
    
                // "This form is not for us!";
                // figure out how (if is possible) to return the get default view here
                // and call it with the right arguments
            }
        } 
    

    3) 将其报告为错误。

    我该在这里做什么?我倾向于把这看作一个bug

    编辑: 我需要强调的一件非常重要的事情是,这两个POST方法都被调用了,所以它不仅仅是一个嵌套形式。

    编辑2: 在Fiddler中,我只看到一个请求。问题是当它试图呈现 联系我们表格 在处理完主页的POST后,它会点击“ContactUsForm”的“POST”方法,而不是非POST处理程序。

    2 回复  |  直到 16 年前
        1
  •  3
  •   tvanfosson    16 年前

    EDIT2 :我刚刚注意到您使用的是RenderAction而不是RenderPart。我怀疑正在发生的事情是,当调用RenderAction时,它正在使用发布表单的RequestContext来选择要选择的ContactUsForm方法。这可以说是正确的行为,因为行动 从回发中调用,但不是您想要的回发。我会以完全不同的方式处理这个问题。使用ViewUserControl生成部分,并使用RenderPart将其包含在页面上。删除GET ContactUsForm方法,只保留POST版本。也就是说,表单本身是作为ViewUserControl生成的,带有通过ViewData传递的参数预先确定或动态生成的标记。表单响应通过控制器动作处理。

    编辑 :既然你表示嵌套不是问题,那么你是否有可能使用javascript(比如jQuery)来触发提交,而你的选择器太宽了。例如,如果你有如下代码,这将解释你所看到的行为。

    $(document).ready( function() {
        $('#mybutton').click( function() {
           $('form').submit();
        });
    });
    

    原始答案: (左为上下文)

    听起来你的视图中有嵌套的表单。尝试将RenderAction移动到父视图中的窗体外,看看是否可以解决您的问题。我对MVC视图中的表单的感觉是,它们应该紧凑,只覆盖包含实际输入的标记。这与WebForms不同,在WebForms中,您通常将所有标记都包装在表单中。如果您需要让表单元素看起来混合在一起,请使用CSS来控制布局。

        2
  •  1
  •   David    15 年前

    这实际上是ASP。NET MVC 1.0与MVC功能库和ASP。netmvc2.0。 当请求为POST时,RenderAction的行为不正确。 我已经在ASP中提交了这个bug。Codeplex上的NET问题跟踪器,请投票:) http://aspnet.codeplex.com/WorkItem/View.aspx?WorkItemId=5847