QueryString参数如何绑定到Action方法参数?

时间:2013-05-21 10:35:01

标签: asp.net asp.net-mvc c1-cms

我有一个webforms项目,我正在尝试运行一些代码,允许我调用MVC路由,然后在Web表单页面的主体内呈现结果。

有一些HttpResponse / Request / Context包装器用于执行对MVC路由的调用,例如:

private static string RenderInternal(string path)
{
  var responseWriter = new StringWriter();

  var mvcResponse = new MvcPlayerHttpResponseWrapper(responseWriter, PageRenderer.CurrentPageId);
  var mvcRequest = new MvcPlayerHttpRequestWrapper(Request, path);
  var mvcContext = new MvcPlayerHttpContextWrapper(Context, mvcResponse, mvcRequest);

  lock (HttpContext.Current)
  {
    new MvcHttpHandlerWrapper().PublicProcessRequest(mvcContext);
  }

  ...

该代码适用于执行简单的MVC路由,例如“/首页/索引”。但我不能指定任何查询字符串参数(例如“/ Home / Index?foo = bar”),因为它们只是被忽略。我试图直接在RequestWrapper实例中设置QueryString,如下所示:

public class MvcPlayerHttpRequestWrapper : HttpRequestWrapper
{
  private readonly string _path;
  private readonly NameValueCollection query = new NameValueCollection();

  public MvcPlayerHttpRequestWrapper(HttpRequest httpRequest, string path)
    : base(httpRequest)
  {
    var parts = path.Split('?');

    if (parts.Length > 1)
    {
      query = ExtractQueryString(parts[1]);
    }

    _path = parts[0];
  }

  public override string Path
  {
    get
    {
      return _path;
    }
  }

  public override NameValueCollection QueryString
  {
    get
    {
      return query;
    }
  }

  ...

调试时我可以在“request.QueryString”中看到正确的值,但这些值永远不会绑定到method参数。

有谁知道如何使用QueryString值并将其从http请求绑定到MVC控制器操作?

似乎QueryString值的处理比我预期的更复杂。我对MVC请求管道的内部知识知之甚少。

我一直在尝试自己研究内部,并将继续这样做。如果我发现任何内容,我会适当更新这篇文章。

我还创建了一个非常简单的Web表单项目,其中只包含产生此问题所需的代码并通过dropbox共享它:https://www.dropbox.com/s/vi6erzw24813zq1/StackMvcGetQuestion.zip 该项目只包含一个Default.aspx页面,一个Controller,以及用于呈现MVC路径结果的MvcWrapper类。如果查看Default.aspx.cs,您将看到传入包含querystring参数的路径路径,但它永远不会绑定操作上的参数。

作为快速参考,以下是该网络项目的一些摘录。

控制器:

public class HomeController : Controller
{
  public ActionResult Index(string foo)
  {
    return Content(string.Format("<p>foo = {0}</p>", foo));
  }
}

Default.aspx页面:

protected void Page_Load(object sender, EventArgs e)
{
  string path = "/Home/Index?foo=baz";

  divMvcOutput.InnerHtml = MvcWrapper.MvcPlayerFunctions.Render(path);
}

我一直在努力解决这个问题已经有一段时间了,所以我会很感激任何形式的建议。 :)

2 个答案:

答案 0 :(得分:0)

MVC框架将尝试从查询字符串(以及其他可用数据,如发布的表单字段等)填充操作方法的参数值,这部分是您正确的。您错过的部分是它通过将参数的名称与传入的值名称相匹配来实现。因此,如果您在Controller MyController中有一个带有签名的方法MyMethod:

public ActionResult MyMethod(string Path)
{
    //Some code goes here
}

查询字符串(或其他变量源之一)必须包含一个名为“Path”的变量,以便框架能够检测到它。查询字符串应为/ MyController / MyMethod?Path = Baz

答案 1 :(得分:0)

确定。这是一个很长的调试会话:)这将是一个很长的响应,所以忍受我:)

首先MVC是如何工作的。当您使用输入参数调用action方法时,框架将调用名为“DefaultModelBinder”的类,该类将尝试为每个基本类型(int,long等)和复杂类型(对象)的实例提供值。此模型绑定器将依赖于名为ValueProvider集合的东西来查找查询字符串,提交的表单等中的变量名称。最感兴趣的ValueProviders之一是QueryStringValueProvider。您可以猜到,它获取查询字符串中定义的变量。在框架内部,此类调用HttpContext.Current来检索查询字符串的值,而不是依赖于传递给它的值。在您的设置中,这使它看到使用localhost:xxxx / Default.aspx的原始请求作为底层请求,导致它看到一个空查询字符串。实际上在Action方法(在你的情况下为Bar)中你可以得到值this.QueryString [“variable”]并且它将具有正确的值。   我修改了Player.cs文件,使用Web客户端调用在VS的单独副本中运行的MVC应用程序,并且它运行良好。所以我建议你单独运行你的mvc应用程序并调用它,它应该可以正常工作。