5

.NET 1.1/IIS6 の時代に誕生した、長期にわたって実行されている ASP.NET Web フォーム アプリケーションがあります。現在、.NET4.5/IIS7 を使用していますが、MVC では何もしていません。

お客様にカタログを提供し、使用できる URL を提供します。

www.ourhost.com/customername

私たちが開発したカスタム IHttpModule を使用して、URL から 'customername' を引き出して、データベース内の顧客を見つけます。その顧客の ID は、ページのコンテキスト* に保存され、その顧客向けにコンテンツをカスタマイズするためにサイト上のほぼすべてのページで使用されます。このプロセスの後、上記の URL は次のように書き換えられて処理されます。

www.ourhost.com/index.aspx

index.aspx を使用すると、そのコンテキストを介して顧客の ID にアクセスでき、その目的を果たすことができます。

これはうまく機能し、数千の顧客をサポートしています。顧客のアカウントを検証し、顧客が無効な場合は「うーん」ページにリダイレクトし、顧客が支払いをしていない場合は別の「ディーラーを探す」ページにリダイレクトするなど、書き換えロジックはかなり複雑です。

今、私はいくつかの Web API コントローラーを作成したいと思っていますが、MVC スタイルの書き換えが心配です。書き換えによってこのような URL が機能する例を数多く見てきました。

www.ourhost.com/api/{controller}

しかし、これらの Web API の「呼び出し」が顧客のコンテキストで発生する必要があります。私たちのページは JSON/AJAX 非同期呼び出しでより洗練されていますが、これらの呼び出しに応答するには、まだ顧客のコンテキストが必要です。URLを

www.ourhost.com/customername/api/{controller}

しかし、ルーティングを構成してこれを行う方法と、IHttpModule でうまく動作させる方法について困惑しています。

これは可能ですか?

*UPDATE: 「ページ コンテキストに保存される」と言うとき、ページ/リクエスト固有のデータを保存できる辞書を含む各 Web リクエストに関連付けられた HttpContext を意味します。

4

1 に答える 1

2

私が見ることができるあなたの問題に対する答えには2つの部分があります。

複数のリクエスト間でユーザー情報を維持する 通常、MVC API アプリケーションはステートレスです。つまり、リクエスト間で現在のユーザーのセッション状態を保持しません。これは、私が RESTFul API を作成する際に何度も学んだり説教されたりしたことです。

そうは言っても、global.asax.cs に以下を追加することで、MVC Web API でセッション状態を有効にできます。

    protected void Application_PostAuthorizeRequest()
    {
        // To enable session state in the WebAPI.
        System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);
    }

リクエストで顧客を承認する リクエスト URL で示したように、顧客名を追加し、それをキャプチャして、現在の http モジュールが要求時に承認するために呼び出す同じルーチンに渡すことができます。これは、MVC フィルターを使用して行うことができます。

最初に同様の URL パターンを実行して、WebApiConfig.cs で顧客名をキャプチャします。

        config.Routes.MapHttpRoute(
            name: "WithCustomerApi",
            routeTemplate: "api/{customername}/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

次に、各リクエストを処理し、現在のセッション情報をチェックし、必要に応じて承認/顧客検索コードを呼び出し、後で使用するためにセッション状態に保存する API コントローラーに ActionFilter を追加します。または、顧客からの適切な情報が新しい MVC ルートに送信できない場合

したがって、次のような属性を追加します。

[WebApiAuthentication]
public class BaseApiController : ApiController
{
}

次に、次のようなアクション フィルターを作成します (これはテストしていないことに注意してください。方法のパターンとして行っただけです)。

public class WebApiAuthenticationAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var routeData = actionContext.ControllerContext.Request.GetRouteData();
        var currentContext = HttpContext.Current;

        if (routeData.Route.RouteTemplate.Contains("customername"))
        {
            try
            {
                var authenticated = currentContext.Request.IsAuthenticated;
                if (!authenticated)
                {
                    var customer = routeData.Values["customername"];
                    // do something with customer here and then put into session or cache
                    currentContext.Session.Add("CustomerName", customer);
                }
            }
            catch (Exception exception)
            {
                var error = exception.Message;
                // We dont like the request
                actionContext.Response = new HttpResponseMessage(HttpStatusCode.BadRequest);
            }
        }
        else
        {
            // No customer name specified, send bad request, not found, what have you ... you *could* potentially redirect but we are in API so it probably a service request rather than a user
            actionContext.Response = new HttpResponseMessage(HttpStatusCode.NotFound);
        }

    }
}

新しい MVC 5 Web API アプリケーションを作成し、これらのエクストラを追加して、デフォルト値コントローラーにフィルターを配置すると、これが可能なソリューションのデモとして実行されていることがわかるはずです。

すべてが正常に機能する場合、これにより顧客名がエコーバックされます。

[WebApiAuthentication]
public class ValuesController : ApiController
{
    // GET api/values
    public IEnumerable<string> Get()
    {
        var session = HttpContext.Current.Session;

        if (session != null)
        {
            return new string[] {"session is present", "customer is", session["CustomerName"].ToString()};
        }

        return new string[] { "value1", "value2" };
    }

}

セッションの保存とAPIでの承認については宗教的な議論がありますが、それらは問題ではありません。お役に立てば幸いです、スティーブ

于 2014-10-16T22:25:11.943 に答える