我尝试创建一个基于Html.RenderAction工作方式的HtmlHelper。与RenderAction不同的方式是" ActionName"和" ControllerName",它取一个字符串,该字符串又对应于Web.Config中的值。配置中的此值是URL的值。
这样做的原因是虽然我的Controller / Action在它自己的原生项目中完美运行,但我需要从它的兄弟项目中获得此Controller / Action的结果。我打算通过使用帮助程序构建所需的URL以及当前在每个兄弟项目的Web.Config中保存的详细信息来实现此目的。
我已经有以下编码:
public static void RenderActionToSpecifiedAssembly(this HtmlHelper helper, string actionName, string controllerName, string parentAssembly)
{
var uriFromWebConfig = new Uri(ConfigurationManager.AppSettings[parentAssembly]);
//uriFromWebConfig == "http://ProjectNumberOne.com/"
var parentUri = new Uri(uriFromWebConfig);
var path = controllerName + "/" + actionName;
var redirect = new Uri(parentUri, path).AbsoluteUri;
//var redirect == "http://ProjectNumberOne.com/MyController/MyAction"
//******************
}
我现在正在努力解决的问题是**********的内容。我希望这个助手做的是返回 http://ProjectNumberOne.com/MyController/MyAction 的结果。
我不知道该怎么做是在帮助程序的末尾指定兄弟项目的返回URL以从中获取生成的html。
有什么想法吗?
答案 0 :(得分:0)
您帖子中的某些细节很难确定您是否希望通过反射或使用 http 来实现目标(或者您可能不在乎只要你能得到你想要的结果。
我不建议您尝试利用反射来实现此目的。 (这有很多原因,但重要的是使用http将变得更容易,更直接)
根据您发布的内容,我将使用的方法是创建一个HtmlHelper
,其IFRAME
标记所需的网址为src
。
像这样的东西(这里有很多机会进行防御性编码BTW):
public static MvcHtmlString RenderIFrameForCompanionSite(this HtmlHelper helper, string actionName, string controllerName, string baseUrlSettingKey)
{
var baseUrlFromWebConfig = ConfigurationManager.AppSettings[baseUrlSettingKey];
var companionSiteUri = new Uri(baseUrlFromWebConfig);
var path = controllerName + "/" + actionName;
var redirect = new Uri(companionSiteUri, path).AbsoluteUri;
return new MvcHtmlString("<iframe style='width: 100%' src='" + redirect + "'></iframe>");
}
ProjectTwo
网站中的视图会引用ProjectOne
中的操作,如下所示:
@Html.RenderIFrameForCompanionSite("MyAction", "MyController", "ProjectOne")
我假设您的应用程序有业务需要在不同的站点/项目中。但是,如果这不是强制性的,那么您可以考虑是否可以以不同方式组织相关内容(例如,具有多个区域而不是多个站点的单个站点),这将使您更容易共享它们之间的内容/行为。
答案 1 :(得分:0)
我发现尽管David提供的IFRAME方法按要求工作,但使用IFRAME仍然让我感到不安。这篇文章让我意识到他们并不是那么伟大:Good Reasons why not to use Iframes in page content
我发现以下实现符合它的目的并给了我所需的结果:
public static IHtmlString RenderActionToSpecifiedAssembly(this HtmlHelper helper, string actionName, string controllerName, string parentAssembly)
{
var parentWebConfigarentValue = new Uri(ConfigurationManager.AppSettings[parentAssembly]);
var path = controllerName + "/" + actionName;
var redirect = new Uri(parentWebConfigarentValue, path).AbsoluteUri;
var request = (HttpWebRequest)WebRequest.Create(redirect);
var result = (HttpWebResponse)request.GetResponse();
String responseString;
using (Stream stream = result.GetResponseStream())
{
StreamReader reader = new StreamReader(stream, Encoding.UTF8);
responseString = reader.ReadToEnd();
}
return new HtmlString(responseString);
}
使用这种方法,我可以向Parent Controller / Action发出请求,将其写入字符串然后将HTML返回到要呈现的页面。有魅力! :)
答案 2 :(得分:0)
您的解决方案可以更好地解释您的需求,但非常不灵活。如果您需要将其他路由值传递给请求,该怎么办?最好通过提供可用于构建任何所需URL的重载来模仿UrlHelper类。
using System;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
public static class HtmlHelperExtensions
{
public static IHtmlString RenderActionToSpecifiedAssembly(
this HtmlHelper helper, string actionName, string parentAssembly)
{
return RenderActionToSpecifiedAssembly(
helper, actionName, null, null, null, parentAssembly);
}
public static IHtmlString RenderActionToSpecifiedAssembly(
this HtmlHelper helper, string actionName, object routeValues,
string parentAssembly)
{
return RenderActionToSpecifiedAssembly(helper, actionName,
null, new RouteValueDictionary(routeValues), null, parentAssembly);
}
public static IHtmlString RenderActionToSpecifiedAssembly(
this HtmlHelper helper, string actionName, string controllerName,
string parentAssembly)
{
return RenderActionToSpecifiedAssembly(helper, actionName,
controllerName, null, null, parentAssembly);
}
public static IHtmlString RenderActionToSpecifiedAssembly(
this HtmlHelper helper, string actionName, RouteValueDictionary routeValues,
string parentAssembly)
{
return RenderActionToSpecifiedAssembly(helper, actionName,
null, routeValues, null, parentAssembly);
}
public static IHtmlString RenderActionToSpecifiedAssembly(
this HtmlHelper helper, string actionName, string controllerName,
object routeValues, string parentAssembly)
{
return RenderActionToSpecifiedAssembly(helper, actionName,
controllerName, new RouteValueDictionary(routeValues),
null, parentAssembly);
}
public static IHtmlString RenderActionToSpecifiedAssembly(
this HtmlHelper helper, string actionName, string controllerName,
RouteValueDictionary routeValues, string parentAssembly)
{
return RenderActionToSpecifiedAssembly(helper, actionName,
controllerName, routeValues, parentAssembly, null);
}
public static IHtmlString RenderActionToSpecifiedAssembly(
this HtmlHelper helper, string actionName, string controllerName,
object routeValues, string protocol, string parentAssembly)
{
return RenderActionToSpecifiedAssembly(helper, actionName,
controllerName, routeValues, protocol, parentAssembly, null);
}
public static IHtmlString RenderActionToSpecifiedAssembly(
this HtmlHelper helper, string actionName, string controllerName,
RouteValueDictionary routeValues, string parentAssembly, string port)
{
var hostName = ConfigurationManager.AppSettings[parentAssembly];
var url = GenerateContentUrl(helper, actionName,
controllerName, routeValues, null, hostName, port);
return RenderContents(url);
}
public static IHtmlString RenderActionToSpecifiedAssembly(
this HtmlHelper helper, string actionName, string controllerName,
object routeValues, string protocol, string parentAssembly, string port)
{
var hostName = ConfigurationManager.AppSettings[parentAssembly];
var url = GenerateContentUrl(helper, actionName,
controllerName, new RouteValueDictionary(routeValues),
protocol, hostName, port);
return RenderContents(url);
}
private static string GenerateContentUrl(this HtmlHelper helper,
string actionName, string controllerName, RouteValueDictionary routeValues,
string protocol, string hostName, string port)
{
var currentUri = helper.ViewContext.RequestContext.HttpContext.Request.Url;
// Ensure we have an absolute path
if (string.IsNullOrEmpty(protocol) && string.IsNullOrEmpty(hostName))
{
// Match the scheme of the current request so we don't get a
// security warning in the browser.
protocol = currentUri.Scheme;
}
// Allow caller to override the port so it doesn't have
// to be the same as the current request.
string currentUrl = currentUri.Scheme + Uri.SchemeDelimiter
+ currentUri.DnsSafeHost;
if (!string.IsNullOrEmpty(port))
{
currentUrl += ":" + port;
}
currentUrl += "/";
var homePageUri = new Uri(new Uri(currentUrl, UriKind.Absolute), "/");
// Create a TextWriter with null stream as a backing stream
// which doesn't consume resources
using (var nullWriter = new StreamWriter(Stream.Null))
{
// Create a fake context at the home page to ensure that ambient values
// from the request are excluded from the generated URL.
// See: https://aspnetwebstack.codeplex.com/workitem/1346
var httpContext = CreateHttpContext(homePageUri, nullWriter);
var requestContext = new RequestContext(httpContext, new RouteData());
return UrlHelper.GenerateUrl(null, actionName, controllerName,
protocol, hostName, null, routeValues, helper.RouteCollection,
requestContext, true);
}
}
private static HttpContextBase CreateHttpContext(Uri uri, TextWriter writer)
{
if (uri == null)
throw new ArgumentNullException("uri");
if (writer == null)
throw new ArgumentNullException("writer");
var request = new HttpRequest(string.Empty, uri.ToString(), uri.Query);
var response = new HttpResponse(writer);
var httpContext = new HttpContext(request, response);
return new HttpContextWrapper(httpContext);
}
private static IHtmlString RenderContents(string url)
{
var request = (HttpWebRequest)WebRequest.Create(url);
var result = (HttpWebResponse)request.GetResponse();
String responseString;
using (Stream stream = result.GetResponseStream())
{
StreamReader reader = new StreamReader(stream, Encoding.UTF8);
responseString = reader.ReadToEnd();
}
return new HtmlString(responseString);
}
}
您可能还希望从配置值中解析端口,以便您可以在其中配置http和https URL,因此它们与主机名紧密绑定在一起,这可能会消除一些重载。在这种情况下,您应该使用当前请求的协议来确定要检索的哪个(HTTP或HTTPS)配置值,并将协议作为传入值删除。