ドット文字「。」api / people / STAFF.45287などのリクエスト用のMVC Web API 2


106

私が機能させようとしているURLは、http://somedomain.com/api/people/staff.33311 のスタイルの1つです(LAST.FMがサイトのようにRESTFulとWebPageのURLにあらゆる種類の記号を許可しているように)たとえば、「http://www.last.fm/artist/psy'aviah」はLAST.FMの有効なURLです)。

どのような作品には、シナリオを以下の通りです: - http://somedomain.com/api/people/ -すべての人々を返す- http://somedomain.com/api/people/staff33311 -同様に動作し、それがどのようなI」ではないでしょう次の例のように、URLに「ドット」を受け入れたい後のm- http://somedomain.com/api/people/staff.33311-これにより、

HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.

私は以下のものをセットアップしました:

  1. コントローラ「PeopleController」

    public IEnumerable<Person> GetAllPeople()
    {
        return _people;
    }
    
    public IHttpActionResult GetPerson(string id)
    {
        var person = _people.FirstOrDefault(p => p.Id.ToLower().Equals(id.ToLower()));
        if (person == null)
            return NotFound();
    
        return Ok(person);
    }    
  2. WebApiConfig.cs

    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
    
        // Web API routes
        config.MapHttpAttributeRoutes();
    
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }

私はすでにこのブログ投稿のすべてのヒントhttp://www.hanselman.com/blog/ExperimentsInWackinessAllowingPercentsAnglebracketsAndOtherNaughtyThingsInTheASPNETIISRequestURL.aspxを試してみましたが、それでもまだ機能しません。より良い、より安全な方法。

私たちは内部的にこのようなIDを持っているので、ドットを何らかの方法で、できれば「。」のスタイルでフィットさせるためのソリューションを見つける必要があります。しかし、必要に応じて、URLの代替提案を受け入れます...


10
ない答えは、これだけにと、なぜ your'reがために404になっsomedomain.com/api/people/staff.33311を -デフォルトでは、このURLでルックスをIISと見ています。ファイル拡張子として、MVC APIをバイパスして静的ファイルハンドラーを呼び出します。受け入れた回答(すべての要求に対してすべてのマネージモジュールを実行)が機能するのは、IISへのすべての要求を強制的にASP.NETパイプライン(したがって、コントローラー)を通過させるためです
Henry C

密接に関連する投稿はこちら
RBT

回答:


104

web.configファイルの次の設定で問題が解決するはずです。

<configuration>
    <system.webServer>
        <modules runAllManagedModulesForAllRequests="true" />

4
それはトリックをしました。しかし、このオプションを設定することによる脆弱性はありますか?なぜこれが標準的な動作ではないのですか?
Yves Schelpe、2014年

2
[OK]を、誰の利益のために:私は見る(カピルKhandelwalによって答え)執筆の時点で受け入れ答えにここで答えされている以上、私の質問:stackoverflow.com/questions/11048863/...
イヴSchelpe

2
はい、それは機能しました、他のバス、私はこの機能が機能するために必要な特定のモジュールを知りたいですか?
グレッグZ. 14年

3
これを試したとき、パスの最後に「/」を置いた場合にのみ機能します。これはなぜですか?余談ですが、すべてのモジュールを実行する代わりに「UrlRoutingModule」を具体的に追加する以下の答えも私にとってはうまくいきましたが、動作するためには最後に「/」が必要であるという問題もありました。
Nikolaj Dam Larsen 2014

10
stackoverflow.com/a/12151501/167018は、runAllManagedModulesForAllRequestsを有効にした場合のパフォーマンスへの影響を懸念している場合は(そして当然のことながら)検討する価値があります。
Henry C

140

URLの末尾にスラッシュを付けます(例:のhttp://somedomain.com/api/people/staff.33311/代わりに)http://somedomain.com/api/people/staff.33311


3
@AgustinMeriles私の回答は、実際の回答よりも回避策と考えることができます。質問の解釈によって異なります。
Danny Varod、2015年

5
ただし、ドットが/ people / memberのようにURLセクションの最後にある場合は機能しません。
eYe 2015年

2
いいえ、最後にスラッシュが必要ない場合はどうなりますか?!必須ではありません。
Josh M.

1
@JoshM。これは回避策です。私はASP.NETを記述しませんでした。また、スラッシュはリクエストに影響を与えません。ただし、とgoogle.com/my query goes here/比較して、意図をより明確にするのに役立ちますgoogle.com/subDomain my query goes here
ダニーVarod

1
はい、これはweb.configを変更する必要のない最高の方法です。
ティモシーゴンザレス2017

35

標準が私のために問題を解決する前に、以下を追加することがわかりました:ExtensionlessUrlHandler

<add name="ExtensionlessUrlHandler-Integrated-4.0-ForApi"
     path="api/*"
     verb="*"
     type="System.Web.Handlers.TransferRequestHandler"
     preCondition="integratedMode,runtimeVersionv4.0" />

名前が実際にはそれほど重要ではないと思いますが、IDE(私の場合はVisual Studio)がサイト構成を管理している場合に役立つでしょう。

H / Tからhttps://stackoverflow.com/a/15802305/264628


標準ラインの「後に」追加しましたが、これも問題なく動作しました。
Jalal El-Shaer 2017

これは受け入れられる答えになるはずです。不要/ uriの終わり
daudihus

2
それが後に働いていなかったので、BEFOREをありがとう!
Mese

モジュールは宣言の順序で実行されると思うので、常により具体的な(またはより重要な)モジュールを、より一般的なモジュールの前に置きます。
BrianS 2018

24

私は本当に何をしているのかわかりませんが、前の答えを少し試した後、おそらくもっと適切な別の解決策を思いつきました。

<system.webServer>
<modules>
    <remove name="UrlRoutingModule-4.0" />
    <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" />
</modules>
</system.webServer>

おかげで、私はそれが何をしているのかわかりませんが、他の解決策よりも良く見えます。
Thomas

1
urlルーティングモジュール(リクエストに拡張子が含まれていることをキャッチし、それをファイルとして処理しようとしている)をモジュールのリストの最後に移動するように見えます。これは、apiリクエストを処理するモジュールの後に置くのに十分です。私見、これは私がSOで見たものから利用可能な最良の回避策です。少なくともATTOW
James Manning

1
これはリストの最後への再配置ではなく、このモジュールがマネージハンドラーに対してのみ実行されるというデフォルトの前提条件の削除です。デフォルトの設定では、この形式を使用しています:<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="managedHandler" />
シータ-魚

ありがとう-これは動作を説明します。
グレッグZ.

8

runAllManagedModulesForAllRequests属性をに設定するだけでは不十分ですtrue。また、拡張子のないURLハンドラーがすべてのパスを参照するように構成されていることを確認する必要がありました。さらに、追加できるボーナス設定がもう1つあります。これは場合によっては役立ちます。これが私の作業中のWeb.configです。

<system.web>
    <httpRuntime relaxedUrlToFileSystemMapping="true" />
</system.web>
<system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <handlers>
        <remove name="WebDAV" />
        <remove name="OPTIONSVerbHandler" />
        <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
        <add name="ExtensionlessUrlHandler-Integrated-4.0"  path="*" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
</system.webServer>

特に、の属性ExtensionlessUrlHandler-Integrated-4.0は(たとえば)ではなくにpath設定さ*れていることに注意してください*.


ちょっと気になったpath="*."。気になるのは、人々がそれを設定した理由は何path="*."ですか?
JustinP8 2016年

実際、私はそれをに変更しpath="*"、問題がありました。WebAPIと一緒にドキュメンテーションサイトをホストしていて、そのサイトには.jpg、.png、および拡張子のある他のファイルに関する問題があったためです。
JustinP8 2016年

@ JustinP8あなたも設定しました<modules runAllManagedModulesForAllRequests="true" />か?これにより、.NETがこれらの静的ファイルを処理できるようになります。
Josh M.

1
はい。私はそれをやった。すべての静的ファイルが.NETパイプラインを通過するようになったので、私はあまり好きではありません。幸い、これはwebAPIサービスであるため、API docs / helperサイトのSwaggerおよびSwashbuckle関連のもののみが影響を受けます。
JustinP8 2016年

これがすべての静的ファイル要求を壊したことがわかりました。エラー500。runAllManaged...をtrueに設定しました。
Sam

2

私はこの状況で行き詰まりましたが/ 、URLの最後に追加することは私にはきれいに見えませんでした。

したがって、以下をweb.config handlersタグに追加するだけで、問題ありません。

<add name="Nancy" path="api" verb="*" type="Nancy.Hosting.Aspnet.NancyHttpRequestHandler" allowPathInfo="true" />

ナンシーとは何か、それがプロジェクトに含まれるライブラリであるかどうかを説明できますか?ありがとう!
青みがかった

1

次のように、runAllManagedModulesForAllRequestsをtrueに設定するか、ExtentionlessUrlHandlerを追加することで、両方の方法が機能することがわかりました。最後に、runAllManagedModulesForAllRequestsはサイトのパフォーマンスに影響を与えるため、extensionUrLHandlerを追加することを選択します。

<handlers>
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <remove name="OPTIONSVerbHandler" />
  <remove name="TRACEVerbHandler" />
  <remove name="WebDAV" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*" verb="*" 
       type="System.Web.Handlers.TransferRequestHandler" 
       preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>

1

これをWeb.configファイルで使用します。

<add name="ManagedSpecialNames" path="api/people/*" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />

標準の「ExtensionlessUrlHandler」の前。

例えば私の場合、私はそれをここに入れました:

<handlers>
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <remove name="OPTIONSVerbHandler" />
  <remove name="TRACEVerbHandler" />
  <add name="ManagedFiles" path="api/people/*" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>

そのため、このようなパターンのURLは、アプリケーションディレクトリツリー内のファイルとしての標準的な管理ではなく、強制的に管理する必要があります。


0

私はまったく同じ問題に直面し、IISやWebサイトの構成関連の設定を操作することになっていない状況にありました。したがって、コードレベルでのみ変更を加えることで機能させる必要がありました。

簡単なポイントは、URLにドット文字が含まれる最も一般的なケースは、ユーザーから入力を取得し、それをクエリ文字列またはURLフラグメントとして渡して、アクションメソッドのパラメーターに引数を渡す場合です。あなたのコントローラーの。

public class GetuserdetailsbyuseridController : ApiController
{
     string getuserdetailsbyuserid(string userId)
     {
        //some code to get user details
     }
}

ユーザーが自分のユーザーIDを入力して個人情報を取得するURLを以下で見てください。

http://mywebsite:8080/getuserdetailsbyuserid/foo.bar

サーバーからデータをフェッチするだけなので、http GET動詞を使用します。GET呼び出しを使用している間、入力パラメーターはURLフラグメントでのみ渡すことができます。

したがって、私の問題を解決するために、私のアクションのhttp動詞をに変更しましたPOST。Http POST動詞には、ユーザーまたは非ユーザーの入力を本文で渡す機能もあります。だから私はJSONデータを作成し、それをhttp POSTリクエストのボディに渡しました:

{
  "userid" : "foo.bar"
}

以下のようにメソッド定義を変更します。

public class GetuserdetailsbyuseridController : ApiController
{
     [Post]
     string getuserdetailsbyuserid([FromBody] string userId)
     {
        //some code to get user details
     }
}

:使用する際の詳細GET動詞とするときに使用するPOST動詞こちら


REST APIを構築している場合は、適切なソリューションではありません。
Mustafa Ozturk
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.