public static string ToHtml(this ViewResult result, HttpContext httpContext) { try { IRoutingFeature feature = httpContext.Features.Get <IRoutingFeature>(); RouteData routeData = feature.RouteData; string viewName = result.ViewName ?? routeData.Values["action"] as string; ActionContext actionContext = new ActionContext(httpContext, routeData, new ControllerActionDescriptor()); IOptions <MvcViewOptions> options = httpContext.RequestServices.GetRequiredService <IOptions <MvcViewOptions> >(); Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelperOptions htmlHelperOptions = options.Value.HtmlHelperOptions; Microsoft.AspNetCore.Mvc.ViewEngines.ViewEngineResult viewEngineResult = result.ViewEngine?.FindView(actionContext, viewName, true) ?? options.Value.ViewEngines.Select(x => x.FindView(actionContext, viewName, true)).FirstOrDefault(x => x != null); Microsoft.AspNetCore.Mvc.ViewEngines.IView view = viewEngineResult.View; StringBuilder builder = new StringBuilder(); using (StringWriter output = new StringWriter(builder)) { ViewContext viewContext = new ViewContext(actionContext, view, result.ViewData, result.TempData, output, htmlHelperOptions); view .RenderAsync(viewContext) .GetAwaiter() .GetResult(); } return(builder.ToString()); } catch { return(string.Empty); } }
public void Attribute_Behaves_As_Expected(IRoutingFeature wrongRouting, [Frozen] IRoutingFeature routing, HttpContext context, IHttpContextAccessor accessor) { Assert.NotSame(wrongRouting, routing); Assert.IsAssignableFrom <DefaultHttpContext>(context); Assert.Same(routing, context.Features[typeof(IRoutingFeature)]); Assert.Same(routing, accessor.HttpContext.Features[typeof(IRoutingFeature)]); routing.RouteData.Values.Add("foo", "bar"); Assert.Equal("bar", accessor.HttpContext.GetRouteValue("foo")); }
public void Customize_EmptyList_WhenRouteValueIsMissing([Frozen] IRoutingFeature routing, RouteBasedRoleCusomizer customizer, string[] allowedRoles, string routeValue) { customizer.IncludeOriginals = true; routing.RouteData.Values.Add("differentName", routeValue); List <string>?result = customizer.CustomizeRoles(allowedRoles).ToList(); Assert.Empty(result); }
public void Customize_ShouldReturnOriginals_WhenFlagNotSet([Frozen] IRoutingFeature routing, RouteBasedRoleCusomizer customizer, string[] allowedRoles, string routeValue) { customizer.IncludeOriginals = false; routing.RouteData.Values.Add(customizer.RouteName, routeValue); List <string>?result = customizer.CustomizeRoles(allowedRoles).ToList(); //Should have only updated roles Assert.Equal(allowedRoles.Length, result.Count); //No intersection between original roles and customized roles Assert.Empty(result.Intersect(allowedRoles)); }
/// <summary> /// Gets the page name as a readable string. /// </summary> /// <param name="routing">The <see cref="IRoutingFeature"/> instance.</param> /// <returns>A readable string form of the page name, if available; otherwise, <c>null</c>.</returns> public static string GetPageName(this IRoutingFeature routing) { if (routing == null) { return(null); } var attributeRouteHandler = routing.RouteData.Routers.OfType <MvcAttributeRouteHandler>().FirstOrDefault(); if (attributeRouteHandler?.Actions.FirstOrDefault() is ControllerActionDescriptor action) { return($"{action.ControllerName}.{action.ActionName}"); } return(attributeRouteHandler?.Actions.FirstOrDefault()?.DisplayName); }
public void Customize_ShouldReturnOriginals_WhenFlagSet([Frozen] IRoutingFeature routing, RouteBasedRoleCusomizer customizer, string[] allowedRoles, string routeValue) { customizer.IncludeOriginals = true; routing.RouteData.Values.Add(customizer.RouteName, routeValue); List <string>?result = customizer.CustomizeRoles(allowedRoles).ToList(); //Should have double the roles Assert.Equal(allowedRoles.Length * 2, result.Count); //All original roles are in there. Assert.Equal(allowedRoles.Length, result.Intersect(allowedRoles).Count()); }
private RouteData SetupRouteData(string controllerName = Controller, string actionName = Action) { _fhirRequestContext.RouteName.Returns((string)null); var routeData = new RouteData(); routeData.Values.Add("controller", controllerName); routeData.Values.Add("action", actionName); IRoutingFeature routingFeature = Substitute.For <IRoutingFeature>(); routingFeature.RouteData.Returns(routeData); _httpContext.Features[typeof(IRoutingFeature)] = routingFeature; return(routeData); }
public async Task <string> RenderPartialViewToString <T>(T dataModel, string partialViewPath) { // we need action context that we will use to find given view path and to construct view context... IRoutingFeature routingFeature = httpAccessor.HttpContext.Features.Get <IRoutingFeature>(); ActionContext actionContext = new ActionContext(httpAccessor.HttpContext, routingFeature.RouteData, new ActionDescriptor()); ViewEngineResult viewEngineResult = razorEngine.FindView(actionContext, partialViewPath, false); IView view; if (viewEngineResult.Success) { view = viewEngineResult.View; } else { // view not found ... throw exception with paths that were searched... ViewEngineResult getViewResult = razorEngine.GetView(null, partialViewPath, false); IEnumerable <string> searchedPaths = getViewResult.SearchedLocations.Concat(viewEngineResult.SearchedLocations); string errorMessage = string.Join(Environment.NewLine, new[] { $"Unable to find view '{ partialViewPath }'. The following locations were searched:" }.Concat(searchedPaths));; throw new InvalidOperationException(errorMessage); } using (StringWriter writer = new StringWriter()) { // create view context that can be used for redering it later... ViewContext viewContext = new ViewContext( actionContext, view, new ViewDataDictionary <T>(new EmptyModelMetadataProvider(), new ModelStateDictionary()) { Model = dataModel // view data... this is our model that will be used to populate the view. }, new TempDataDictionary(actionContext.HttpContext, tempDataProvider), writer, // text writer. options.Value.HtmlHelperOptions ); // render the view now using view context that will populate the string writer. await view.RenderAsync(viewContext); return(writer.ToString()); } }
/// <summary> /// Gets the route as a readable string. /// </summary> /// <param name="routing">The <see cref="IRoutingFeature"/> instance.</param> /// <returns>A readable string form of the route, if available; otherwise, <c>null</c>.</returns> public static string GetRouteString(this IRoutingFeature routing) { if (routing == null) { return(null); } var templateRoute = routing.RouteData.Routers.OfType <Route>().FirstOrDefault(); if (templateRoute != null) { if (routing.RouteData.Values.TryGetValue("controller", out var controller) && routing.RouteData.Values.TryGetValue("action", out var action)) { return($"{controller}.{action}"); } } var attributeRoute = routing.RouteData.Routers.OfType <MvcAttributeRouteHandler>().FirstOrDefault(); return(attributeRoute?.Actions.FirstOrDefault()?.AttributeRouteInfo?.Template); }
/// <summary> /// Helper method to get the odata path for an arbitrary odata uri. /// </summary> /// <param name="request">The request instance in current context</param> /// <param name="uri">OData uri</param> /// <returns>The parsed odata path</returns> #if NETCORE public static ODataPath CreateODataPath(this HttpRequest request, Uri uri) { if (uri == null) { throw new ArgumentNullException("uri"); } // Clone the features so that a new set is used for each context. // The features themselves will be reused but not the collection. We // store the request container as a feature of the request and we don't want // the features added to one context/request to be visible on another. // // Note that just about everything in the HttpContext and HttpRequest is // backed by one of these features. So reusing the features means the HttContext // and HttpRequests are the same without needing to copy properties. To make them // different, we need to avoid copying certain features to that the objects don't // share the same storage/ IFeatureCollection features = new FeatureCollection(); foreach (KeyValuePair <Type, object> kvp in request.HttpContext.Features) { // Don't include the OData features. They may already // be present. This will get re-created later. // // Also, clear out the items feature, which is used // to store a few object, the one that is an issue here is the Url // helper, which has an affinity to the context. If we leave it, // the context of the helper no longer matches the new context and // the resulting url helper doesn't have access to the OData feature // because it's looking in the wrong context. // // Because we need a different request and response, leave those features // out as well. if (kvp.Key == typeof(IODataBatchFeature) || kvp.Key == typeof(IODataFeature) || kvp.Key == typeof(IItemsFeature) || kvp.Key == typeof(IHttpRequestFeature) || kvp.Key == typeof(IHttpResponseFeature)) { continue; } features[kvp.Key] = kvp.Value; } // Add in an items, request and response feature. features[typeof(IItemsFeature)] = new ItemsFeature(); features[typeof(IHttpRequestFeature)] = new HttpRequestFeature(); features[typeof(IHttpResponseFeature)] = new HttpResponseFeature(); // Create a context from the factory or use the default context. HttpContext context = new DefaultHttpContext(features); // Clone parts of the request. All other parts of the request will be // populated during batch processing. context.Request.Cookies = request.HttpContext.Request.Cookies; foreach (KeyValuePair <string, StringValues> header in request.HttpContext.Request.Headers) { context.Request.Headers.Add(header); } // Copy the Uri. context.Request.Scheme = uri.Scheme; context.Request.Host = uri.IsDefaultPort ? new HostString(uri.Host) : new HostString(uri.Host, uri.Port); context.Request.QueryString = new QueryString(uri.Query); context.Request.Path = new PathString(uri.AbsolutePath); // Get the existing OData route IRoutingFeature routingFeature = context.Features[typeof(IRoutingFeature)] as IRoutingFeature; ODataRoute route = routingFeature.RouteData.Routers.OfType <ODataRoute>().FirstOrDefault(); // Attempt to route the new request and extract the path. RouteContext routeContext = new RouteContext(context); route.RouteAsync(routeContext).Wait(); return(context.Request.ODataFeature().Path); }