Adding URL generation to WebFX for controllers and views
This follows a similar pattern to html helpers - a minimal basis interface that performs the main functionality, and a set of extension methods that make up the rich API.
This commit is contained in:
parent
9af7c2bbfb
commit
0ce2c511d4
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace MvcSample
|
||||
{
|
||||
public class LinkController : Controller
|
||||
{
|
||||
public IActionResult Details()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
public string About()
|
||||
{
|
||||
return Url.Action(null);
|
||||
}
|
||||
|
||||
public string Get()
|
||||
{
|
||||
return Url.Route(new { controller = "Home", action = "Details" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -49,6 +49,7 @@ namespace MvcSample
|
|||
new { controller = "Home" });
|
||||
|
||||
builder.UseRouter(routes);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
|
||||
@Url.Action("About")
|
||||
|
|
@ -1,19 +1,23 @@
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Abstractions;
|
||||
using Microsoft.AspNet.Routing;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class ActionContext
|
||||
{
|
||||
public ActionContext(HttpContext httpContext, IDictionary<string, object> routeValues, ActionDescriptor actionDescriptor)
|
||||
public ActionContext(HttpContext httpContext, IRouter router, IDictionary<string, object> routeValues, ActionDescriptor actionDescriptor)
|
||||
{
|
||||
HttpContext = httpContext;
|
||||
Router = router;
|
||||
RouteValues = routeValues;
|
||||
ActionDescriptor = actionDescriptor;
|
||||
}
|
||||
|
||||
public HttpContext HttpContext { get; private set; }
|
||||
|
||||
public IRouter Router { get; private set; }
|
||||
|
||||
public IDictionary<string, object> RouteValues { get; private set; }
|
||||
|
||||
public ActionDescriptor ActionDescriptor { get; private set; }
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
{
|
||||
string locationsText = String.Join(Environment.NewLine, result.SearchedLocations);
|
||||
const string message = @"The view '{0}' was not found. The following locations were searched:{1}.";
|
||||
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, message, viewName, locationsText));
|
||||
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, message, viewName, locationsText));
|
||||
}
|
||||
|
||||
return result.View;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
public HttpContext Context { get; set; }
|
||||
|
||||
public IRenderUrl Url { get; set; }
|
||||
|
||||
public ViewData<object> ViewData { get; set; }
|
||||
|
||||
public dynamic ViewBag
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
{
|
||||
Action = action,
|
||||
};
|
||||
var actionContext = new ActionContext(context.HttpContext, context.RouteValues, action);
|
||||
var actionContext = new ActionContext(context.HttpContext, null, context.RouteValues, action);
|
||||
var actionBindingContext = await _bindingProvider.GetActionBindingContextAsync(actionContext);
|
||||
|
||||
foreach (var parameter in action.Parameters.Where(p => p.ParameterBindingInfo != null))
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ using System.Reflection;
|
|||
using Microsoft.AspNet.Abstractions;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Routing;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
|
|
@ -58,6 +59,15 @@ namespace Microsoft.AspNet.Mvc
|
|||
{
|
||||
prop.SetValue(controller, modelState);
|
||||
}
|
||||
else if (prop.Name == "Url" && prop.PropertyType == typeof(IRenderUrl))
|
||||
{
|
||||
var generator = new DefaultRenderUrl(
|
||||
actionContext.HttpContext,
|
||||
actionContext.Router,
|
||||
actionContext.RouteValues);
|
||||
|
||||
prop.SetValue(controller, generator);
|
||||
}
|
||||
}
|
||||
|
||||
var method = controllerType.GetRuntimeMethods().FirstOrDefault(m => m.Name.Equals("Initialize", StringComparison.OrdinalIgnoreCase));
|
||||
|
|
@ -72,6 +82,5 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
method.Invoke(controller, args);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Abstractions;
|
||||
using Microsoft.AspNet.Routing;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class DefaultRenderUrl : IRenderUrl
|
||||
{
|
||||
private readonly HttpContext _httpContext;
|
||||
private readonly IRouter _router;
|
||||
private readonly IDictionary<string, object> _ambientValues;
|
||||
|
||||
public DefaultRenderUrl(HttpContext httpContext, IRouter router, IDictionary<string, object> ambientValues)
|
||||
{
|
||||
_httpContext = httpContext;
|
||||
_router = router;
|
||||
_ambientValues = ambientValues;
|
||||
}
|
||||
|
||||
public virtual string Action(string action, string controller, object values)
|
||||
{
|
||||
var valuesDictionary = new RouteValueDictionary(values);
|
||||
|
||||
if (action != null)
|
||||
{
|
||||
valuesDictionary["action"] = action;
|
||||
}
|
||||
|
||||
if (controller != null)
|
||||
{
|
||||
valuesDictionary["controller"] = controller;
|
||||
}
|
||||
|
||||
return RouteCore(valuesDictionary);
|
||||
}
|
||||
|
||||
public virtual string Route(object values)
|
||||
{
|
||||
return RouteCore(new RouteValueDictionary(values));
|
||||
|
||||
}
|
||||
|
||||
protected virtual string RouteCore(IDictionary<string, object> values)
|
||||
{
|
||||
var context = new VirtualPathContext(_httpContext, _ambientValues, values);
|
||||
var path = _router.GetVirtualPath(context);
|
||||
|
||||
// We need to add the host part in here, currently blocked on http abstractions support.
|
||||
// The intent is to use full URLs by default.
|
||||
return _httpContext.Request.PathBase + path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -62,7 +62,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
return;
|
||||
}
|
||||
|
||||
var actionContext = new ActionContext(context.HttpContext, context.Values, actionDescriptor);
|
||||
var actionContext = new ActionContext(context.HttpContext, context.Router, context.Values, actionDescriptor);
|
||||
var invoker = ActionInvokerFactory.CreateInvoker(actionContext);
|
||||
if (invoker == null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ using System.Text;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Abstractions;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
|
|
@ -17,10 +16,14 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
|
||||
protected TextWriter Output { get; set; }
|
||||
|
||||
public IRenderUrl Url { get; set; }
|
||||
|
||||
private string BodyContent { get; set; }
|
||||
|
||||
public virtual async Task RenderAsync(ViewContext context, TextWriter writer)
|
||||
{
|
||||
Url = context.RenderUrl;
|
||||
|
||||
var contentBuilder = new StringBuilder(1024);
|
||||
using (var bodyWriter = new StringWriter(contentBuilder))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
|
|
@ -17,6 +16,8 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
|
||||
public HtmlHelper<TModel> Html { get; set; }
|
||||
|
||||
public IRenderUrl RenderUrl { get; set; }
|
||||
|
||||
public override Task RenderAsync(ViewContext context, TextWriter writer)
|
||||
{
|
||||
var viewData = context.ViewData as ViewData<TModel>;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public interface IRenderUrl
|
||||
{
|
||||
string Action(string action, string controller, object values);
|
||||
|
||||
string Route(object values);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public static class RenderUrlExtension
|
||||
{
|
||||
public static string Action(this IRenderUrl generator)
|
||||
{
|
||||
return generator.Action(null, null, null);
|
||||
}
|
||||
|
||||
public static string Action(this IRenderUrl generator, string action)
|
||||
{
|
||||
return generator.Action(action, null, null);
|
||||
}
|
||||
|
||||
public static string Action(this IRenderUrl generator, string action, object values)
|
||||
{
|
||||
return generator.Action(action, null, values);
|
||||
}
|
||||
|
||||
public static string Action(this IRenderUrl generator, string action, string controller)
|
||||
{
|
||||
return generator.Action(action, controller, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue