私は MVC 3 のソース コードを調べ、MVC 4 でテストし、その方法を発見しました。質問に間違ったタグを付けました... MVC 3用ではなく、MVC 4を使用しています.MVC 3コードを見て解決策を見つけることができたので、MVC 3でも動作する可能性があります
最後に... 試行錯誤を繰り返しながら 5 時間の調査を行う価値があることを願っています。
で動作します
- MVC 3(だと思います)
- MVC 4 (テスト済み)
私のソリューションの欠点
残念ながら、このソリューションは非常に複雑で、私があまり好きではないものに依存しています。
- 静的オブジェクト
ControllerBuilder.Current
(単体テストには非常に悪い)
- MVC からの多くのクラス(高結合は常に悪い)
- 普遍的ではありません (MVC 3 の既定のオブジェクトでは機能しますが、MVC から派生した他の実装では機能しない可能性があります。たとえば、派生した MvcHandler、カスタム IControllerFactory など...)
- 内部の依存関係(MVC 3 の特定の側面に依存します (MVC 4 もこのように動作します)、MVC 5 は異なる場合があります。たとえば
RouteData
、コントローラーの種類を見つけるためにオブジェクトが使用されないことがわかっているため、単純にスタブ RouteData オブジェクトを使用します)
- データを渡すための複雑なオブジェクトのモック (モック
HttpContextWrapper
を作成し、をorHttpRequestWrapper
に設定する必要がありました... これらの非常に単純な値は、複雑なオブジェクトから取得されます (なんてこった! =\ ))http method
POST
GET
コード
public static Attribute[] GetAttributes(
this Controller @this,
string action = null,
string controller = null,
string method = "GET")
{
var actionName = action
?? @this.RouteData.GetRequiredString("action");
var controllerName = controller
?? @this.RouteData.GetRequiredString("controller");
var controllerFactory = ControllerBuilder.Current
.GetControllerFactory();
var controllerContext = @this.ControllerContext;
var otherController = (ControllerBase)controllerFactory
.CreateController(
new RequestContext(controllerContext.HttpContext, new RouteData()),
controllerName);
var controllerDescriptor = new ReflectedControllerDescriptor(
otherController.GetType());
var controllerContext2 = new ControllerContext(
new MockHttpContextWrapper(
controllerContext.HttpContext.ApplicationInstance.Context,
method),
new RouteData(),
otherController);
var actionDescriptor = controllerDescriptor
.FindAction(controllerContext2, actionName);
var attributes = actionDescriptor.GetCustomAttributes(true)
.Cast<Attribute>()
.ToArray();
return attributes;
}
編集
モッククラスを忘れた
class MockHttpContextWrapper : HttpContextWrapper
{
public MockHttpContextWrapper(HttpContext httpContext, string method)
: base(httpContext)
{
this.request = new MockHttpRequestWrapper(httpContext.Request, method);
}
private readonly HttpRequestBase request;
public override HttpRequestBase Request
{
get { return request; }
}
class MockHttpRequestWrapper : HttpRequestWrapper
{
public MockHttpRequestWrapper(HttpRequest httpRequest, string httpMethod)
: base(httpRequest)
{
this.httpMethod = httpMethod;
}
private readonly string httpMethod;
public override string HttpMethod
{
get { return httpMethod; }
}
}
}
これがすべて誰かに役立つことを願っています...
みんなでハッピーコーディング!