2

MVC 4 ApiController のコントローラーで Server.MapPath(virtualPath) メソッドにアクセスする必要があります。

答えは通常、ControllerContext.HttpContext.Server からアクセスすることです。ただし、MvcControllers とは異なり、ApiController の ControlerContext には HttpContext がありません。

Global.asax.cs でインスタンス化された WebApiAppication には、HttpContext 要素 (Context) があります。ただし、MVC 3 以前とは異なり、コントローラーから WebApiApplication にアクセスする方法が見つかりません。(以前の世代では、それへの参照が静的インスタンス変数に格納されていました。MVC 4 ではそれが削除されています。)

また、ユニット Test からコントローラー メソッドを呼び出すときに、余分な足場がなくても機能するものを見つけようとしています。WebApi コントローラーでも、HttpContext.Current を使用してアクセスできると思います (少なくともコンパイルされます) が、テストのためにそれをモックすることはできません。(ここでは、Controller メソッドを直接呼び出す単体テストについて説明しています。最近のチュートリアルで、薄い HttpClient を使用して単体テストを行い、スタック全体をテストするのを見てきました。これは、低レベルの統合テストのように思えます。私に。)

これはそれほど難しいことではないように思えますが、私はそれをグーグルで調べたり試したりするのに数時間を費やしました。

4

2 に答える 2

1

この機能を抽象化することをお勧めします。

public interface IMyDependency
{
    string MapPath(string path);
}

そして実装があります:

public class MyConcreteDependency: IMyDependency
{
    public string MapPath(string path)
    {
        return HostingEnvironment.MapPath(path);
    }
}

最後に、ApiController はすべての静的メソッド呼び出しから完全に独立しており、単体テストに適しています。

public class MyController: ApiController
{
    private readonly IMyDependency dependency;
    public MyController(IMyDependency dependency)
    {
        this.dependency = dependency;
    }

    public HttpResponseMessage Get()
    {
        var path = this.dependency.MapPath("~/App_Data");
        ...
    }
}
于 2013-02-25T09:24:55.500 に答える
0

のためApiControllersに、自分自身を構築し、DelegatingHandlerすべてのグッズを に押し込みますrequest.Properties。その後、テスト中かライブ実行中かを問わず、リクエストからそれらを取得できます。利点は、コントローラーのセッションに依存しないことです。

MessageHandler

public class ContextHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        // get the goodies to add onto the request
        var goodies = /* call to goodieGoodieYumYum */


        // add our goodies onto the request
        request.Properties.Add(Constants.RequestKey_Goodies, goodies);

        // pass along to the next handler
        return base.SendAsync(request, cancellationToken);
    }
}

コントローラ アクション

var goodies = (List<Goodie>)Request.Properties[Constants.RequestKey_Goodies];
于 2014-03-21T17:07:52.357 に答える