Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 4.0 web api从内部处理程序获取路由模板_C# 4.0_Asp.net Web Api_Asp.net Web Api2_Asp.net Web Api Routing - Fatal编程技术网

C# 4.0 web api从内部处理程序获取路由模板

C# 4.0 web api从内部处理程序获取路由模板,c#-4.0,asp.net-web-api,asp.net-web-api2,asp.net-web-api-routing,C# 4.0,Asp.net Web Api,Asp.net Web Api2,Asp.net Web Api Routing,在把问题放在这里之前我搜索了很多,但是搜索得越多,我就越困惑 因此,我创建了一个处理程序,并尝试获得如下路径: public class ExecutionDelegatingHandler : DelegatingHandler { protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)

在把问题放在这里之前我搜索了很多,但是搜索得越多,我就越困惑

因此,我创建了一个处理程序,并尝试获得如下路径:

public class ExecutionDelegatingHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        if (securityAuthority.VerifyPermissionToExecute(request.GetRouteData().Route.RouteTemplate, request.Headers))
        {
            return base.SendAsync(request, cancellationToken);
        }
        else
        {
            httpResponseMessage.StatusCode = HttpStatusCode.Unauthorized;
        }
    }
 }
这个路由运行得很好,但奇怪的是,如果我试图让控制器为这个请求提供服务,我会得到一个404。。。如果我跳过这一步,我会很好地到达控制器

HttpControllerDescriptor httpControllerDescriptor = request.GetRequestContext().Configuration.Services.GetHttpControllerSelector().SelectController(request);
IHttpController httpController = httpControllerDescriptor.CreateController(request);
我使用autofac来发现我定义的所有路线,就像:

[Route("queries/organization/clients")]
[HttpGet]
public ClientInitialScreenModel GetClients()
{
    return OrganizationModelsBuilder.GetClientInitialScreen();
}
更新2

如果在上述行之后调用GetRouteData,则我能够获取路由模板:

base.SendAsync(request, cancellationToken);

var routeData = request.GetRouteData();
所以,也许我误解了整个情况,在解析为请求执行哪个控制器的处理程序开始工作之前,我无法获得路由模板。。。是这样吗

作为参考,这是我正在处理的处理程序:

公共类ExecutionDelegatingHandler:DelegatingHandler
{
受保护的覆盖任务SendAsync(HttpRequestMessage请求,CancellationToken CancellationToken)
{
var securityAuthority=(ISecurityAuthority)request.GetDependencyScope().GetService(typeof(ISecurityAuthority));
var配置=(IWebAppConfiguration)request.GetDependencyScope().GetService(typeof(IWebAppConfiguration));
var tsc=new TaskCompletionSource();
var httpResponseMessage=新httpResponseMessage();
if(request.RequestUri.AbsolutePath.Equals(configuration.CommandGatewayUrl、StringComparison.InvariantCultureIgnoreCase))
{
var apiMessage=JsonConvert.DeserializeObject(request.Content.ReadAsStringAsync().Result);
if(securityAuthority!=null&!securityAuthority.VerifyPermissionToExecute(apiMessage,request.Headers))
{
httpResponseMessage.StatusCode=HttpStatusCode.Unauthorized;
}
其他的
{
var messageProcessor=(IWebApiMessageProcessor)request.GetDependencyScope().GetService(typeof(IWebApiMessageProcessor));
var-reponse=messageProcessor.HandleRequest(apiMessage);
httpResponseMessage.StatusCode=(HttpStatusCode)reponse.StatusCode;
如果(!string.IsNullOrEmpty(response.Content))
{
httpResponseMessage.Content=新的StringContent(reponse.Content);
}
}
}
其他的
{
if(securityAuthority!=null&!securityAuthority.VerifyPermissionToExecute(request.GetRouteData().Route.RouteTemplate,request.Headers))
{
httpResponseMessage.StatusCode=HttpStatusCode.Unauthorized;
}
其他的
{
返回base.sendaync(请求、取消令牌);
}
}
tsc.SetResult(httpResponseMessage);
返回tsc任务;
}
更新3


代码在非自托管环境中运行良好,因此这更像是一个自托管问题。

Web Api仍有很多改进。找到一种方法使其工作起来很困难,我只是希望这可以避免其他人花费我所有的时间

 var routeTemplate = ((IHttpRouteData[]) request.GetConfiguration().Routes.GetRouteData(request).Values["MS_SubRoutes"])
                                    .First().Route.RouteTemplate;

我也遇到了类似的问题,但通过以下方法可以在消息处理程序中获取路由:

request.GetConfiguration().Routes.GetRouteData(request.Route.RouteTemplate;

来自Marco(如下所示)的答案是正确的,只要使用相同的HttpMethod定义的路由不超过一个。
.First()
将获取在特定的
ApiController
中定义的第一条路由,但这并不确保它获取正确的路由。如果使用
ControllerContext
获取路由,您可以确保获得了所需的确切端点

马可:

var routeTemplate = ((IHttpRouteData[])request.GetConfiguration()
                     .Routes.GetRouteData(request).Values["MS_SubRoutes"])
                     .First().Route.RouteTemplate;
守则:

((IHttpRouteData[])request.GetConfiguration()
                     .Routes.GetRouteData(request).Values["MS_SubRoutes"])
实际上,返回一个
IHttpRouteData
的集合,它包含每个端点的一条记录,这些端点具有相同的HttpMethod(Post、Get等).
.First()
不能保证您得到想要的端点

保证获取正确端点的
路由模板

public static string GetRouteTemplate(this HttpActionContext actionContext)
{
    return actionContext.ControllerContext.RouteData.Route.RouteTemplate;
} 
我使用了一个扩展方法来调用它,您可以这样做:

var routeTemplate = actionContext.GetRouteTemplate();

这将确保您从进行调用的端点获取特定的
RouteTemplate

我认为您可以从request.Properties属性和易于单元测试中获取路由数据

/// <summary>
    /// Gets the <see cref="System.Web.Http.Routing.IHttpRouteData"/> for the given request or null if not available.
    /// </summary>
    /// <param name="request">The HTTP request.</param>
    /// <returns>The <see cref="System.Web.Http.Routing.IHttpRouteData"/> or null.</returns>
    public static IHttpRouteData GetRouteData(this HttpRequestMessage request)
    {
        if (request == null)
        {`enter code here`
            throw Error.ArgumentNull("request");
        }

        return request.GetProperty<IHttpRouteData>(HttpPropertyKeys.HttpRouteDataKey);
    }

    private static T GetProperty<T>(this HttpRequestMessage request, string key)
    {
        T value;
        request.Properties.TryGetValue(key, out value);
        return value;
    }
//
///获取给定请求的值,如果不可用,则为null。
/// 
///HTTP请求。
///无效或无效。
公共静态IHttpRouteData GetRoutedData(此HttpRequestMessage请求)
{
if(请求==null)
{`在这里输入代码`
抛出错误。ArgumentNull(“请求”);
}
return request.GetProperty(HttpPropertyKeys.HttpRouteDataKey);
}
私有静态GetT属性(此HttpRequestMessage请求,字符串键)
{
T值;
request.Properties.TryGetValue(key,out值);
返回值;
}

还没有测试过这个问题,但至少可以说这很奇怪,但无论如何,很多事情都没有正确完成,我只是希望ASP.Net vNext能够修复。很抱歉,我错过了答案。你的代码可以工作,我指的是@Shivan ahmady的另一个答案。好吧,因为我发现我的代码为什么不能在基本c上工作真的很奇怪ontroller.对我来说非常有用;添加到DelegatingHandler以记录所有正在使用的路由非常有用,因此您可以通过数据驱动决定哪些API终结点可以被淘汰,而不会导致太多破坏性的更改。是的,我也这样做。我还使用委托进行访问验证。角色由多个组成路线,这样我就可以控制对每条路线的访问。
var routeTemplate = actionContext.GetRouteTemplate();
/// <summary>
    /// Gets the <see cref="System.Web.Http.Routing.IHttpRouteData"/> for the given request or null if not available.
    /// </summary>
    /// <param name="request">The HTTP request.</param>
    /// <returns>The <see cref="System.Web.Http.Routing.IHttpRouteData"/> or null.</returns>
    public static IHttpRouteData GetRouteData(this HttpRequestMessage request)
    {
        if (request == null)
        {`enter code here`
            throw Error.ArgumentNull("request");
        }

        return request.GetProperty<IHttpRouteData>(HttpPropertyKeys.HttpRouteDataKey);
    }

    private static T GetProperty<T>(this HttpRequestMessage request, string key)
    {
        T value;
        request.Properties.TryGetValue(key, out value);
        return value;
    }