调用MVC UserControls的POST方法及其父视图

时间:2009-02-07 12:51:46

标签: asp.net-mvc

改写:我原来的帖子似乎被误解了。我已经将其报告为具有以下描述的错误。我可以在第二个<HR&gt;下面找到此问题的原始帖子。


我在用户控件中遇到POST的主要问题。

  • 我有一个UserControl,它有一个包含两个名为'ContactForm'的ActionMethods的控制器。第二个有ActionVerb.POST就可以回复帖子了。用户控件主要通过AJAX使用 - 但这实际上与此无关。显然,这些动作方法呈现局部视图。

  • 我有一个主页面,其中包含“EnterContest”的其他html表单。再次 - 它的控制器有两个名为'EnterContest'的ActionMethod,其中一个响应ActionVerb.POST。此视图在侧栏中包含“ContactForm”,使用以下内容进行渲染:

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

回发'EnterContest'表单(视图中的主窗体)时会出现问题。

来自Fiddler的POST请求只包含此查询字符串(显然不包含来自联系我们表单的任何POST数据,因为这是一个完全独立的HTTP ACTION)。

  

contestId = ND09&安培;电子邮件= fred的&安培; btnEnterContest =提交

     

(是的,这看起来像一个GET,但那就是   Fiddler为POST展示了什么)

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

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

如果我看一下堆栈跟踪 - 它是从动态生成的aspx页面调用的 - 源自上面显示的Html.RenderAction代码行。显然,正在发生的事情是寻求部分呈现'ContactUs'动作方法的代码查看Request并看到有一种方法来处理POST,因此它将它路由到那里 - 这很糟糕。它可能在框架中围绕这个方法:

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

这种行为非常令人困惑,真的打破了一个简单的页面。我很确定这是一个错误 - 因为如果我的控制器中没有一些非常笨拙的检查,我就看不到优雅的工作。我认为RenderAction是期货 - 但我不知道问题是存在于那里还是存在于主框架中。

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

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

由于


原帖

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

我遇到了意想不到的事情,但是当我想到它时,这更有意义。

假设我有一个包含'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方法。在此操作中,formdata属性包含父视图的所有属性 - 因此ContactUsForm会因空引用而死亡。

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

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)将其报告为错误。

我应该在这做什么?我倾向于将此视为一个错误

编辑:我需要强调的一件非常重要的事情是调用两种POST方法 - 所以它不仅仅是像嵌套形式一样的东西。

编辑2:在Fiddler中,我只看到一个请求。问题是当它在我的主页面处理完POST后尝试渲染ContactUsForm时,它会触及'ContactUsForm'而不是非post处理程序的'POST'方法。

2 个答案:

答案 0 :(得分:3)

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

编辑:由于您指出嵌套不是问题,您是否可能使用javascript(例如jQuery)来触发提交,而您的选择器过于宽泛。例如,如果您有类似以下的代码,则会考虑您所看到的行为。

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

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

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

答案 1 :(得分:1)

这实际上是ASP.NET MVC 1.0与MVC功能库和ASP.NET MVC 2.0中的确认错误。 请求为POST时,RenderAction行为不正确。 我在Codeplex上提交了ASP.NET Issue Tracker中的错误,请投票给它:) http://aspnet.codeplex.com/WorkItem/View.aspx?WorkItemId=5847