我有一个基于WCF REST服务模板40(CS)的WCF REST 4.0项目。我想公开简单的服务端点URL 没有 拖延斜线。例如:

  1. CarService.CS
  2. 卡车服务

我将上述URL视为资源请求(不是目录),这就是为什么我认为在这里不适合拖延的原因。

不幸的是,我似乎无法获得我想要的行为,因为我总是被重定向到 /和 /卡车 / 拖延斜线。

这是我定义“汽车”路线和服务方法的方式 - 请注意,我在任何路由或URI模板定义中尚未包含任何斜线:

// Global.asax.cs
RouteTable.Routes.Add(new ServiceRoute("cars", new WebServiceHostFactory(), typeof(CarService)));

// CarService.cs
[WebGet(UriTemplate = "")]
public List<Car> GetCollection()
{
    return DataContext.GetAllCars();
}

请注意,MVC不起作用。使用MapRoute方法,我可以将请求直接路由到 http://www.domain.com/about 没有重定向到 /大约 /。如何在WCF REST 4.0中获得相同的行为?

有帮助吗?

解决方案

您遇到的主要问题是 当前的 WCF REST的版本会导致307重定向(到“/”),当您在webget属性中为uritemplate有一个空字符串。据我所知,当前版本中没有解决这个问题。

但是,鉴于您需要解决方案1)允许您区分服务,而2)(相对)uris有一些“中间基础”解决方案。

第一个解决方案您可以将其放入您的global.asax文件中(per 这个示例)。您可以为每种服务做一个服务路线:

RouteTable.Routes.Add(new ServiceRoute("cars", new WebServiceHostFactory(), typeof(CarService)));
RouteTable.Routes.Add(new ServiceRoute("trucks", new WebServiceHostFactory(), typeof(TruckService)));

此时,您可以在每种服务中填充尿液板:

[WebGet(UriTemplate = "all")]
CarPool GetAllCars();

[WebGet(UriTemplate = "{carName}")]
Car GetCar(string carName);

这将使您的uris:

www.domain.com/cars/all
www.domain.com/cars/123 or www.domain.com/cars/honda

同样适用于卡车:

www.domain.com/trucks/all
www.domain.com/trucks/123 or www.domain.com/trucks/ford

第二个解决方案使用服务主机 休息入门套件 (即,WebServiceHost2Factory)。

RouteTable.Routes.Add(new ServiceRoute("cars", new WebServiceHost2Factory(), typeof(CarService)));

当使用您试图使用上面的URI时,这不会导致307重定向,从而使您完全需要。尽管我意识到使用该服务主机工厂,而不是使用WCF 4发货的工厂感到有些奇怪。

其他提示

您需要一个尿液板,尝试这样的事情:

 [ServiceContract()]
 public interface ICarService
 {

     [OperationContract]
     [WebGet(UriTemplate = "/Car")]
     CarPool GetAllCars();

     [OperationContract]
     [WebGet(UriTemplate = "/Car/{carName}")]
     Car GetCar(string carName);

 }

尝试将其放在global.asax.cs中

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        string rawUrl = HttpContext.Current.Request.RawUrl.ToLower();

        if (rawUrl.EndsWith("/cars"))
        {
            HttpContext.Current.RewritePath(rawUrl + "/");  // append trailing slash
        }
    }

我正在处理这个确切的问题,并在MS在线文档中遇到了这个片段:

默认情况下,路由不处理将其映射到Web服务器上现有物理文件的请求。例如,请求 http://server/application/products/beverages/coffee.aspx 如果在产品/饮料/咖啡中存在物理文件,则无法通过路由来处理。即使请求与定义的模式匹配,例如{Controller}/{action}/{ID},路由也不会处理该请求。

我意识到我的路线模式与目录匹配我的服务已托管。看来目录的处理方式与物理文件相同,并且匹配目录的路由模式也被忽略了。因此,在文档之后,我将RouteexistingFiles属性设置为“ true”。现在,我的服务似乎正确地路由了请求,并且我能够保持我非常非常喜欢的其余语法。

较旧的问题,但这是我如何通过WCF4 REST服务来解决问题(使用Global.asax中的RouteTable添加ServicerOutes)。 IIS7已配置,因此当调用服务时,我有一个空的相对路径,因此处理方法的uritemplate是空的,就像Will的汽车示例一样。我在服务的Web.config文件中使用了重写规则,以添加一个“/”。它始终与路径匹配,然后检查原始URI({request_uri}),以查看它是否包含没有尾随“/”的路径。

    <rewrite>
        <rules>
            <!--
            This rule will append a "/" after "/car" if
            the client makes a request without a trailing "/".
            ASP however must have a trailing "/" to find
            the right handler.
            -->
            <rule name="FixCarPath" stopProcessing="true">
                <match url=".*" />
                <conditions>
                    <add input="{REQUEST_URI}" pattern="/car\?" />
                </conditions>
                <action type="Rewrite" url="{PATH_INFO}/" />
            </rule>
        </rules>
    </rewrite>

更可重复使用:

public class Global : NinjectHttpApplication
{

    protected override void OnApplicationStarted()
    {
        base.OnApplicationStarted();
        RegisterRoutes();
    }

    private void RegisterRoutes()
    {
        RouteTable.Routes.Add(new ServiceRoute("login", new NinjectWebServiceHostFactory(), typeof(LoginService)));
        RouteTable.Routes.Add(new ServiceRoute("incidents", new NinjectWebServiceHostFactory(), typeof(IncidentService)));
        SetRoutePrefixes();
    }
    //This is a workaround for WCF forcing you to end with "/" if you dont have a urlTemplate and redirecting if you dont have
    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        string rawUrl = HttpContext.Current.Request.RawUrl.ToLower();


        if (_routePrefixes.Any(rawUrl.EndsWith))
        {
            HttpContext.Current.RewritePath(rawUrl + "/");  // append trailing slash
        }
    }


    private static List<string> _routePrefixes; 
    private static void SetRoutePrefixes()
    {
        _routePrefixes = new List<string>();
        foreach (var route in RouteTable.Routes)
        {
            var r = route as Route;
            var routePrefix = r.Url.Split('/').First();
            _routePrefixes.Add(routePrefix);
        }
    }

尝试在global.asax中更改您的代码。

Routes.Add(new ServiceRoute("cars", new WebServiceHostFactory(), typeof(CarService))); RouteTable.Routes.Add(new ServiceRoute("trucks", new WebServiceHostFactory(), typeof(TruckService)));

...至...

WebServiceHostFactory factory = new WebServiceHostFactory();

Routes.Add(new ServiceRoute("cars", factory, typeof(CarService))); RouteTable.Routes.Add(new ServiceRoute("trucks", factory, typeof(TruckService)));

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top