[英]Mixing ASP.Net MVC custom routing and partial views in a ASP.Net web forms project
我正在嘗試從以ASP.Net Web表單編寫的CMS緩慢遷移到ASP.Net MVC。 為此,我需要將Web部件(自定義控件)中的功能替換為局部視圖中的功能。 CMS頁面包含許多Web部件,每個Web部件最終都應從MVC部分視圖呈現一些html。 另外,我還需要一種方法來傳遞每個Web部件中設置的參數,並基於這些參數構造局部視圖。 整個目的是將業務邏輯與表示分離,以消除對CMS本身的依賴性。 在此過程中,所有Web部件仍應正常工作。 您對實現此目標的有效方法有任何想法或建議嗎?
這是我的出發點。 我試圖檢索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);
}
}
}
這是我想在Webforms頁面中呈現PartialViews或ChildActions時使用的MvcUtility類,但是我認為我沒有在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,您需要在Shared MVC Views文件夾中有一個局部視圖:
@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 }); %>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.