2014-02-01 3 views
1

Я пытаюсь медленно перемещаться из CMS, написанной в ASP.NET-формах ASP.Net, в ASP.Net MVC. Для этого мне нужно заменить функциональность веб-частей (настраиваемых элементов управления) на функциональность из частичных представлений. Страница CMS содержит множество веб-частей, и каждый из них должен отображать в конечном итоге некоторый html из частичного представления MVC. Также мне нужен способ передать параметры, установленные в каждой веб-части, и на их основе построить частичный вид. Вся цель состоит в том, чтобы отделить бизнес-логику от представления, чтобы удалить зависимость от самой CMS. Во время процесса все веб-части должны работать. Есть ли у вас какие-либо идеи или предложения об эффективном способе достижения этого?Смешивание пользовательской маршрутизации и частичных представлений ASP.Net MVC в проекте веб-форм ASP.Net

Это моя отправная точка. Я пытаюсь получить частичный вид MVC как строку за пределами конвейера ASP.Net. Для этого мне нужно использовать HttpContext. Поскольку у меня нет этого контекста (я хочу использовать только минимальный минимум свойств, переданных через некоторые интерфейсы), я попытался создать поддельный.

public class TestController : Controller, ICmsTranslator 
{ 
    public ActionResult Index() 
    { 
     return View(); 
    } 

    public string RenderAsString(IHttpRequest request, IContext context) 
    { 
     return RenderRazorViewToString("~/Views/Shared/_TestPartialView.cshtml", new TestModels(), request, context); 
    } 

    public string RenderRazorViewToString(string viewName, object model, IHttpRequest request, IContext context) 
    { 
     ViewData.Model = model; 
     using (var sw = new StringWriter()) 
     { 
      // create a fake HttpContext 
      var fakeRouteData = new RouteData(); 
      if (!fakeRouteData.Values.ContainsKey("controller") && !fakeRouteData.Values.ContainsKey("Controller")) 
      { 
       fakeRouteData.Values.Add("controller", GetType().Name 
                  .ToLower() 
                  .Replace("controller", "")); 
      } 
      HttpContextBase offlineContextBase = new OfflineHttpContext(viewName, request, context); 
      var offlineControllerContext = new ControllerContext(offlineContextBase, fakeRouteData, this); 

      // try to use the fake context to get the partial view 
      var viewResult = ViewEngines.Engines.FindPartialView(offlineControllerContext, viewName); 
      var viewContext = new ViewContext(offlineControllerContext, viewResult.View, ViewData, TempData, sw); 
      viewResult.View.Render(viewContext, sw); 
      viewResult.ViewEngine.ReleaseView(offlineControllerContext, viewResult.View); 
      return sw.GetStringBuilder().ToString(); 
     } 
    } 
} 




public class OfflineHttpContext : HttpContextBase 
{ 
    private readonly Hashtable _items = new Hashtable(); 
    private IPrincipal _user; 
    private readonly IHttpRequest _request; 
    private readonly IContext _context; 
    private readonly string _relativeUrl; 

    public OfflineHttpContext(string relativeUrl, IHttpRequest request, IContext context) 
    { 
     _relativeUrl = relativeUrl; 
     _request = request; 
     _context = context; 
    } 

    public override Exception[] AllErrors 
    { 
     get { return new Exception[0]; } 
    } 

    public override Cache Cache 
    { 
     get { return null; } 
    } 

    public override HttpRequestBase Request 
    { 
     get 
     { 
      var serverVariables = new NameValueCollection 
             { 
              {"HTTP_HOST", "www.example.com"}, 
              {"APPL_PHYSICAL_PATH", _context.PhysicalPath} 
             }; 

      var headers = new NameValueCollection(); 
      foreach (var header in _request.Headers) 
      { 
       headers.Add(header.Key, header.Value); 
      } 
      var formParams = new NameValueCollection(); 
      var queryStringParams = new NameValueCollection(); 
      var cookies = new HttpCookieCollection(); 

      HttpRequestBase httpContext = new OfflineHttpRequest(_relativeUrl, _request.Method, formParams, queryStringParams, cookies, serverVariables, headers); 
      return httpContext; 
     } 
    } 

    public override HttpResponseBase Response 
    { 
     get 
     { 
      var httpResponse = new HttpResponse(new StringWriter()); 
      return new HttpResponseWrapper(httpResponse); 
     } 
    } 

    public override IDictionary Items 
    { 
     get { return _items; } 
    } 

    public override IPrincipal User 
    { 
     get 
     { 
      if (_user == null) 
      { 
       // User is logged in 
       return new GenericPrincipal(new GenericIdentity("public"), new string[0]); 
       // User is logged out 
       // return new GenericPrincipal(new GenericIdentity(""), new string[0]); 
      } 
      return _user; 
     } 
     set { _user = value; } 
    } 
} 


public class OfflineHttpRequest : HttpRequestBase 
{ 
    private readonly HttpCookieCollection _cookies; 
    private readonly NameValueCollection _formParams; 
    private readonly NameValueCollection _queryStringParams; 
    private readonly NameValueCollection _headers; 
    private readonly NameValueCollection _serverVariables; 
    private readonly string _relativeUrl; 
    private readonly Uri _url; 
    private readonly Uri _urlReferrer; 
    private readonly string _httpMethod; 

    public OfflineHttpRequest(
     string relativeUrl, 
     string httpMethod, 
     NameValueCollection formParams, 
     NameValueCollection queryStringParams, 
     HttpCookieCollection cookies, 
     NameValueCollection serverVariables, 
     NameValueCollection headers) 
    { 
     _httpMethod = httpMethod; 
     _relativeUrl = relativeUrl; 
     _formParams = formParams; 
     _queryStringParams = queryStringParams; 
     _cookies = cookies; 
     _serverVariables = serverVariables; 
     _headers = headers; 

     //ensure collections are not null 
     if (_formParams == null) 
     { 
      _formParams = new NameValueCollection(); 
     } 
     if (_queryStringParams == null) 
     { 
      _queryStringParams = new NameValueCollection(); 
     } 
     if (_cookies == null) 
     { 
      _cookies = new HttpCookieCollection(); 
     } 
     if (_serverVariables == null) 
     { 
      _serverVariables = new NameValueCollection(); 
     } 
     if (_headers == null) 
     { 
      _headers = new NameValueCollection(); 
     } 
    } 

    public OfflineHttpRequest(
     string relativeUrl, 
     string httpMethod, 
     Uri url, 
     Uri urlReferrer, 
     NameValueCollection formParams, 
     NameValueCollection queryStringParams, 
     HttpCookieCollection cookies, 
     NameValueCollection serverVariables, 
     NameValueCollection headers) 
     : this(relativeUrl, httpMethod, formParams, queryStringParams, cookies, serverVariables, headers) 
    { 
     _url = url; 
     _urlReferrer = urlReferrer; 
     _headers = headers; 
    } 

    public OfflineHttpRequest(
     string relativeUrl, 
     Uri url, 
     Uri urlReferrer) 
     : this(relativeUrl, HttpVerbs.Get.ToString("g"), url, urlReferrer, null, null, null, null, null) 
    { 
    } 

    public override NameValueCollection ServerVariables 
    { 
     get 
     { 
      return _serverVariables; 
     } 
    } 

    public override NameValueCollection Form 
    { 
     get { return _formParams; } 
    } 

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

    public override NameValueCollection Headers 
    { 
     get { return _headers; } 
    } 

    public override HttpCookieCollection Cookies 
    { 
     get { return _cookies; } 
    } 

    public override string AppRelativeCurrentExecutionFilePath 
    { 
     get { return _relativeUrl; } 
    } 

    public override Uri Url 
    { 
     get 
     { 
      return _url; 
     } 
    } 

    public override Uri UrlReferrer 
    { 
     get 
     { 
      return _urlReferrer; 
     } 
    } 

    public override string Path 
    { 
     get 
     { 
      if (_relativeUrl != null && _relativeUrl.StartsWith("~/")) 
      { 
       return _relativeUrl.Remove(0, 1); 
      } 
      return null; 
     } 
    } 

    public override string PathInfo 
    { 
     get 
     { 
      return ""; 
     } 
    } 

    public override string PhysicalApplicationPath 
    { 
     get 
     { 
      return _serverVariables.Get("APPL_PHYSICAL_PATH"); 
     } 
    } 

    public override string PhysicalPath 
    { 
     get 
     { 
      var file = ""; 
      if (Path != null && Path.StartsWith("/")) 
      { 
       file = Path.Remove(0, 1); 
      } 
      if (PhysicalApplicationPath != null) 
      { 
       return PhysicalApplicationPath + "\\" + file.Replace('/', '\\'); 
      } 
      return null; 
     } 
    } 

    public override string HttpMethod 
    { 
     get 
     { 
      return _httpMethod; 
     } 
    } 

    public override string UserHostAddress 
    { 
     get { return null; } 
    } 

    public override string RawUrl 
    { 
     get { return null; } 
    } 

    public override bool IsSecureConnection 
    { 
     get { return false; } 
    } 

    public override bool IsAuthenticated 
    { 
     get 
     { 
      return false; 
     } 
    } 

    public override string UserAgent 
    { 
     get 
     { 
      var agent = _headers.Get("User-Agent") ?? 
          "Mozilla/5.0+(compatible;+Googlebot/2.1;++http://www.google.com/bot.html)"; 
      return agent; 
     } 
    } 

    public override HttpBrowserCapabilitiesBase Browser 
    { 
     get 
     { 
      var browser = new HttpBrowserCapabilities 
      { 
       Capabilities = new Hashtable { { string.Empty, UserAgent } } 
      }; 
      var factory = new BrowserCapabilitiesFactory(); 
      factory.ConfigureBrowserCapabilities(new NameValueCollection(), browser); 

      return new HttpBrowserCapabilitiesWrapper(browser); 
     } 
    } 
} 
+0

Так что это wha t Я пытаюсь использовать, но есть исключение, связанное с тем, что VirtualPath имеет значение null. Когда я использую свой поддельный контекст здесь: ... ViewEngines.Engines.FindPartialView (offlineControllerContext, viewName); ... под капотом VirtualPathProvider использует ASP.NET HttpContext, а не мой поддельный контекст. – bit

ответ

0

Это MvcUtility класса я использую, когда я хотел бы оказать PartialViews или ChildActions в виде WebForms страницы, я не думаю, что я использовал его в UserControl однако.

Не знаете, какую версию MVC вы используете, но я знаю, что это работает с MVC 3 и Razor Views.

public static class MvcUtility 
{ 
     public static void RenderPartial(string partialViewName, object model) 
     { 
      // Get the HttpContext 
      HttpContextBase httpContextBase = new HttpContextWrapper(HttpContext.Current); 
      // Build the route data, pointing to the Some controller 
      RouteData routeData = new RouteData(); 
      routeData.Values.Add("controller", typeof(Controller).Name); 
      // Create the controller context 
      ControllerContext controllerContext = new ControllerContext(new RequestContext(httpContextBase, routeData), new Controller()); 
      // Find the partial view 
      IView view = FindPartialView(controllerContext, partialViewName); 
      // create the view context and pass in the model 
      ViewContext viewContext = new ViewContext(controllerContext, view, new ViewDataDictionary { Model = model }, new TempDataDictionary(), httpContextBase.Response.Output); 
      // finally, render the view 
      view.Render(viewContext, httpContextBase.Response.Output); 
     } 

     private static IView FindPartialView(ControllerContext controllerContext, string partialViewName) 
     { 
      // try to find the partial view 
      ViewEngineResult result = ViewEngines.Engines.FindPartialView(controllerContext, partialViewName); 
      if (result.View != null) 
      { 
       return result.View; 
      } 
      // wasn't found - construct error message 
      StringBuilder locationsText = new StringBuilder(); 
      foreach (string location in result.SearchedLocations) 
      { 
       locationsText.AppendLine(); 
       locationsText.Append(location); 
      } 
      throw new InvalidOperationException(String.Format("Partial view {0} not found. Locations Searched: {1}", partialViewName, locationsText)); 
     } 

     public static void RenderAction(string controllerName, string actionName, object routeValues) 
     { 
      RenderPartial("RenderActionUtil", new RenderActionVM() { ControllerName = controllerName, ActionName = actionName, RouteValues = routeValues }); 
     } 
    } 

Оказывать ChildAction вам потребуется частичный вид в долевом MVC Просмотров Папка:

@model YourNamespace.RenderActionVM 

@{ 
    Html.RenderAction(Model.ActionName, Model.ControllerName, Model.RouteValues); 
} 

А Вид модели:

public class RenderActionVM 
{ 
    public string ControllerName { get; set; } 
    public string ActionName { get; set; } 
    public object RouteValues { get; set; } 
} 

И, наконец, в вашей WebForms страницы вызова например:

<% MvcUtility.RenderPartial("_SomePartial", null); %> 

<% MvcUtility.RenderAction("SomeController", "SomeAction", new { accountID = Request.QueryString["id"], dateTime = DateTime.Now }); %> 
+0

Спасибо, но в моем сценарии HttpContext.Current выдаст исключение, поскольку HttpContext имеет значение null. Вот почему я пытаюсь подделать это. – bit