MVC-从urlreferrer url创建一个ViewModel类实例

时间:2011-07-13 15:10:51

标签: asp.net-mvc

假设:

request.UrlReferrer.LocalPath = "/MyApp/MyHome/List";

我有一个路由映射处理这个,其中MyHome是我的控制器,List是一个采用ViewModel的动作。此路由的其他变体包括分页和排序,但这些变量由ViewModel捕获。

我的问题是:

如何使用上述URL生成相关ViewModel的实例?

编辑:我有一个JQuery对话框,它添加/更新/删除列表中的项目,该列表由urlreferrer中的url显示 - 给出的示例是最基本的。当对话框将数据发送为/ u / d时,我想返回列表的更新主体并显示它。此信息由与对话框中POST实例化的不同ViewModel处理(发布到的URL是“/ MyApp / MyHome / Edit / True” - 用于创建新的任何内容)。这篇文章遵循标准的MVC流程,当然也可以。我想要做的是基于列表操作的ViewModel创建第二 ViewModel,并将其作为包含更新的分页列表的部分视图返回。

1 个答案:

答案 0 :(得分:0)

好的......我想我已经搞清楚了。这不是很漂亮,但它确实有效。我欢迎任何人的输入通过ModelBinder或任何其他MVC工件实际提供这个,但这是我想出的:

首先,我们需要使用UrlReferrer而不是请求的实际网址伪造请求:

public class FakeHttpContext : HttpContextBase
 {
      public FakeHttpContext(HttpContextBase currentContext)
      {
           _request = new FakeHttpRequest(currentContext.Request);
      }

      HttpRequestBase _request;
      public override HttpRequestBase Request
      {
           get
           {
                return _request;
           }
      }

      HttpResponseBase _response = new FakeHttpResponse();
      public override HttpResponseBase Response
      {
           get
           {
                return _response;
           }
      }

      class FakeHttpRequest : HttpRequestBase
      {
           HttpRequestBase _request;

           public FakeHttpRequest(HttpRequestBase currentRequest)
           {
                if(currentRequest == null)
                     throw new ArgumentNullException();

                this._request = currentRequest;
           }

           public override string ApplicationPath
           {
                get
                {
                     return this._request.ApplicationPath;
                }
           }

           public override string AppRelativeCurrentExecutionFilePath
           {
                get
                {
                     return "~" + this._request.UrlReferrer.AbsolutePath.Remove(0, this._request.ApplicationPath.Length);
                }
           }

           public override string PathInfo
           {
                get
                {
                     return this._request.PathInfo;
                }
           }

      }

      class FakeHttpResponse : HttpResponseBase
      {
      }
 }

接下来,我们通过RouteTable提供虚假来电,以便将其分解。并将属性与RouteData.Values匹配。

public static class RouteAndModelBinder
 {
      public static void BuildViewModel<TViewModel>(ControllerContext context, TViewModel model)
      {
           FakeHttpContext fake = new FakeHttpContext(context.HttpContext);
           RouteData test = RouteTable.Routes.GetRouteData(fake);

           PropertyInfo[] properties = typeof(TViewModel).GetProperties();

           string value;

           foreach(PropertyInfo info in properties)
           {
                if(test.Values.ContainsKey(info.Name))
                {
                     value = (string)test.Values[info.Name];

                     if(value == null)
                     {
                          continue;
                     }

                     if(info.PropertyType.IsGenericType &&
                          info.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
                     {
                          Type[] nullables = info.PropertyType.GetGenericArguments();

                          if(nullables.Length > 0)
                          {
                               Type nullableType = nullables[0];

                               if(nullableType.BaseType == typeof(Enum))
                               {
                                    object o = Enum.Parse(nullableType, value);
                                    info.SetValue(model, o, null);
                               }
                               else if(nullableType == typeof(Int32))
                               {
                                    info.SetValue(model, int.Parse(value), null);

                               }
                               else
                               {
                                    info.SetValue(model, Convert.ChangeType(value, info.PropertyType), null);
                               }
                          }

                     }
                     else
                     {
                          if(info.PropertyType.BaseType == typeof(Enum))
                          {
                               object o = Enum.Parse(info.PropertyType.BaseType, value);
                               info.SetValue(model, o, null);
                          }
                          else if(info.PropertyType == typeof(Int32))
                          {
                               info.SetValue(model, int.Parse(value), null);
                          }
                          else
                          {
                               info.SetValue(model, value, null);
                          }

                     }
                }
           }
      }
 }

同样,我欢迎任何人就如何使用已经建立的MVC代码(即ModelBinders等)执行此操作的建议。我从here (可空类型)和here中获取了一些想法和代码。

相关问题