サイトマップにバインドするテレリク mvc メニューがあります。すべてのリンクが適切にセットアップされ、正常にバインドされます。しかし、ポスト メソッドで、無効なモデルのビューにモデルがポスト バックされるView(model)
と、以下のエラーで壊れます。ビューにリダイレクトすると、PRGパターンで正常に動作します。
INFO[System.NullReferenceException: オブジェクト参照がオブジェクトのインスタンスに設定されていません。f:\109\Griffin\Trunk Full\Sources\Source\Telerik.Web.Mvc\Infrastructure\ の Telerik.Web.Mvc.Infrastructure.Implementation.ControllerAuthorization.IsAccessibleToUser (RequestContext requestContext、文字列 controllerName、文字列 actionName、RouteValueDictionary routeValues) でImplementation\ControllerAuthorization.cs: f:\109\Griffin\Trunk Full\Sources\Source\Telerik.Web.Mvc\ の Telerik.Web.Mvc.Infrastructure.Implementation.NavigationItemAuthorization.IsAccessibleToUser(RequestContext requestContext, INavigatable navigationItem) の 75 行目Infrastructure\Implementation\NavigationItemAuthorization.cs:38行目
コードをデバッグすると、内部で System.Web.MVC クラスを呼び出してノードの認証情報を取得することがわかりました。以下は、無効なモデルに対して null を返す行です。それ以外の場合は、リダイレクトまたは通常の GET 操作であれば正常に機能します。
ActionDescriptor actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);
if (actionDescriptor == null)
{
return null; **//it returns null for View(model)**
}
return new AuthorizationContext(controllerContext, actionDescriptor) { Controller = { ControllerContext = controllerContext } };
System.Web.Mvc の FindAction メソッド。RunSelectionFilters
通常の場合と例外の場合で異なる出力を生成するこのメソッドから呼び出されます。
public MethodInfo FindActionMethod(ControllerContext controllerContext, string actionName)
{
List<MethodInfo> matchingAliasedMethods = this.GetMatchingAliasedMethods(controllerContext, actionName);
matchingAliasedMethods.AddRange(this.NonAliasedMethods[actionName]);
List<MethodInfo> ambiguousMethods = RunSelectionFilters(controllerContext, matchingAliasedMethods);
switch (ambiguousMethods.Count)
{
case 0:
return null;
case 1:
return ambiguousMethods[0];
}
throw this.CreateAmbiguousMatchException(ambiguousMethods, actionName);
}
RunSelectionFilters メソッドはlist2
、通常の操作とlist
例外の場合に戻ります。
private static List<MethodInfo> RunSelectionFilters(ControllerContext controllerContext, List<MethodInfo> methodInfos)
{
List<MethodInfo> list = new List<MethodInfo>();
List<MethodInfo> list2 = new List<MethodInfo>();
using (List<MethodInfo>.Enumerator enumerator = methodInfos.GetEnumerator())
{
Func<ActionMethodSelectorAttribute, bool> predicate = null;
MethodInfo methodInfo;
while (enumerator.MoveNext())
{
methodInfo = enumerator.Current;
ICollection<ActionMethodSelectorAttribute> actionMethodSelectorAttributes = ReflectedAttributeCache.GetActionMethodSelectorAttributes(methodInfo);
if (actionMethodSelectorAttributes.Count == 0)
{
list2.Add(methodInfo);
}
else
{
if (predicate == null)
{
predicate = attr => attr.IsValidForRequest(controllerContext, methodInfo);
}
if (actionMethodSelectorAttributes.All<ActionMethodSelectorAttribute>(predicate))
{
list.Add(methodInfo);
}
}
}
}
if (list.Count <= 0)
{
return list2;
}
return list;
}
以下は、カスタム承認属性です。この属性は BaseController に適用されます。
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class AppActionAuthorizeAttribute : FilterAttribute, IAuthorizationFilter
{
protected virtual bool AuthorizeCore(HttpContextBase httpContext)
{
return DBService.IsAuthorized(httpContext.RequestContext().RouteData.Values);
}
public virtual void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (OutputCacheAttribute.IsChildActionCacheActive(filterContext))
{
throw new InvalidOperationException("AuthorizeAttribute cannot be used within a child action caching block.");
}
if (this.AuthorizeCore(filterContext.HttpContext))
{
HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
cache.SetProxyMaxAge(new TimeSpan(0L));
cache.AddValidationCallback(new HttpCacheValidateHandler(this.CacheValidateHandler), null);
}
else
{
this.HandleUnauthorizedRequest(filterContext);
}
}
private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus)
{
validationStatus = this.OnCacheAuthorization(new HttpContextWrapper(context));
}
protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext)
{
if (httpContext == null)
{
throw new ArgumentNullException("httpContext");
}
if (!this.AuthorizeCore(httpContext))
{
return HttpValidationStatus.IgnoreThisRequest;
}
return HttpValidationStatus.Valid;
}
}