19

WCF RESTサービステンプレート40(CS)に基づくWCFREST4.0プロジェクトがあります。末尾にスラッシュを付けずに、単純なサービスエンドポイントURLを公開したいと思います。例えば:

  1. CarService.cs
  2. TruckService.cs

私は上記のURLを(ディレクトリではなく)リソースリクエストと見なしているため、ここでは末尾のスラッシュは適切ではないと思います。

残念ながら、私は常に/cars/と/trucks/にリダイレクトされ、末尾にスラッシュが付いているため、希望する動作が得られないようです。

「車」のルートとサービス方法を定義した方法は次のとおりです。ルートまたは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メソッドを使用すると、/ about /にリダイレクトせずに、リクエストをhttp://www.domain.com/aboutに直接ルーティングできます。WCF REST 4.0で同じ動作を得るにはどうすればよいですか?

4

7 に答える 7

9

発生している主な問題は、WebGet属性にUriTemplateの空の文字列がある場合、現在のバージョンのWCFRESTが(「/」への)307リダイレクトを引き起こすことです。私の知る限り、現在のバージョンではこれを回避することはできません。

ただし、1)サービスを差別化できるソリューション、および2)(比較的)短いURIを持つソリューションが必要な場合、問題には2つの「中間」ソリューションがあります。

最初の解決策 これをglobal.asaxファイルに入れることができます(この例では)。サービスごとにサービスルートを実行できます。

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

この時点で、各サービスにUriTemplateを設定できます。

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

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

これにより、次のURIが可能になります。

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

2番目の解決策RESTスターターキット のサービスホスト(つまり、WebServiceHost2Factory)を使用します。

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

これにより、上記で使用しようとしているURIを使用するときに307リダイレクトが発生しないため、必要なものが正確に提供されます。WCF 4に同梱されているものではなく、そのサービスホストファクトリを使用すると、少し奇妙に感じることはわかりますが。

于 2010-10-20T01:13:58.530 に答える
3

UriTemplateが必要です。次のようなものを試してください:

 [ServiceContract()]
 public interface ICarService
 {

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

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

 }
于 2010-10-19T20:14:27.413 に答える
3

これを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
        }
    }
于 2012-06-01T01:07:51.343 に答える
2

私はこの正確な問題に対処していて、MSオンラインドキュメントでこのスニペットに出くわしました。

デフォルトでは、ルーティングはWebサーバー上の既存の物理ファイルにマップする要求を処理しません。たとえば、Products / Beverages / Coffee.aspxに物理ファイルが存在する場合、http://server/application/Products/Beverages/Coffee.aspxのリクエストはルーティングによって処理されません。{controller} / {action} / {id}などの定義されたパターンに一致する場合でも、ルーティングは要求を処理しません。

ルートパターンがサービスがホストされているディレクトリと一致していることに気付きました。ディレクトリは物理ファイルと同じように扱われ、ディレクトリと一致するルートパターンも無視されるようです。そのため、ドキュメントに従って、RouteCollectionでRouteExistingFilesプロパティを「true」に設定しました。私のサービスはリクエストを正しくルーティングしているように見え、とても気に入っているREST構文を維持することができました。

于 2012-01-03T15:10:18.837 に答える
2

古い質問ですが、WCF4 RESTサービスの問題をどのように解決したかを示します(Global.asaxのRouteTableを使用してServiceRoutesを追加します)。IIS7は、サービスが呼び出されるまでに相対パスが空になるように構成されているため、Will's Carの例のように、処理メソッドのUriTemplateは空になります。サービスの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>
于 2012-05-02T15:00:32.577 に答える
2

もう少し再利用可能:

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);
        }
    }
于 2013-06-18T20:32:21.837 に答える
1

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

于 2010-11-24T19:36:36.740 に答える