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