Pregunta

Tengo un proyecto WCF REST 4.0 basado en la plantilla de servicio WCF el RESTO 40 (CS). Me gustaría exponer las direcciones URL de punto final de servicio simples sin barra final. Por ejemplo:

  1. CarService.cs
  2. TruckService.cs

Miro las URL anteriores como las solicitudes de recursos (no directorios), por lo que no creo barras al final son apropiadas aquí.

Por desgracia, me parece que no puede obtener el comportamiento que quiero porque siempre me redirige a / coches / camiones / y / por de barra al final.

Así es como he definido la ruta "coches" y método de servicio - nota que no he incluido ninguna barras en cualquiera de la ruta o definiciones de plantillas 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();
}

Tenga en cuenta que MVC no funciona de esta manera. Con el método MapRoute que pueda enrutar las solicitudes directamente a http://www.domain.com/about sin una redirección a / sobre / . ¿Cómo puedo obtener el mismo comportamiento en WCF REST 4.0?

¿Fue útil?

Solución

La cuestión principal que se está ejecutando en es que el actual versión de WCF REST provoca una redirección 307 (a la "/") cuando tiene una cadena vacía para el UriTemplate en su WebGet atributo. Por lo que yo sé, no hay forma de evitar esto en la versión actual.

Sin embargo, hay un par de solución "término medio" a su problema teniendo en cuenta que desea una solución que 1) le permite diferenciar los servicios, y 2) tener (relativamente) URI cortos.

Primera Solución Usted puede poner esto en su archivo Global.asax (por este ejemplo ). Usted puede hacer una ruta de servicio para cada servicio:

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

En este punto se puede rellenar su UriTemplate en cada servicio:

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

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

Esto le permitirá URIs de:

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

Del mismo modo para camiones:

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

Segunda Solución Utilice el host de servicio de la REST Starter Kit (es decir, la WebServiceHost2Factory).

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

Esto no se traduce en una redirección 307 cuando se utilizan las URIs que usted está tratando de utilizar arriba y por lo tanto, le da exactamente lo que necesita. Aunque soy consciente de que se siente un poco raro el uso de esa fábrica de host de servicio en lugar de la que se incluye con WCF 4.

Otros consejos

Es necesario un UriTemplate, intentar algo como esto:

 [ServiceContract()]
 public interface ICarService
 {

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

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

 }

Trate de poner esto en el 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
        }
    }

Yo estaba tratando con este problema exacto y corrió a través de este fragmento en el ms documentos en línea:

Por defecto, el enrutamiento no maneja las solicitudes que se asignan a un archivo físico existente en el servidor Web. Por ejemplo, una solicitud de http: //server/application/Products/Beverages/Coffee.aspx no se maneja mediante el enrutamiento si un archivo físico existe en los productos / bebidas / Coffee.aspx. Enrutamiento no maneja la solicitud incluso si coincide con un patrón definido, como {controlador} / {acción} / {id}.

Me di cuenta de que mi patrón de ruta coincide con el directorio de mi servicio fue organizada en. Parece ser que un directorio se trata igual que un archivo físico y patrones de ruta que responden a un directorio se tienen en cuenta también. Así pues, siguiendo la documentación, que establece la propiedad RouteExistingFiles a "true" en el RouteCollection. Mi servicio parece estar encaminar las solicitudes correctamente y he sido capaz de mantener la sintaxis REST que amo muchísimo.

pregunta antiguo pero así es como he resuelto el problema con un servicio WCF4 RESTO (utilizando el RouteTable en Global.asax para agregar ServiceRoutes). IIS7 está configurado para que en el momento en que el servicio se invoca Tengo una ruta relativa vacío, por lo UriTemplate del método de manejo está vacía, como ejemplo de Will coche. He utilizado una regla de reescritura en el archivo web.config del servicio de añadir un "/" si es necesario. Es siempre coincide con la ruta a continuación, comprueba el URI original ({} REQUEST_URI) para ver si contiene un camino sin arrastre "/".

    <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>

Un poco más reutilizables:

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);
        }
    }

Trate de cambiar el código en el Global.asax de ...

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

... a ...

WebServiceHostFactory factory = new WebServiceHostFactory();

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top