0

私は奇妙な問題に遭遇しました。BindModelがActionFilterAttributeの前に実行される

私はPOSTパラメータを取るAPIを持っているASP.NETプロジェクトを持っています。私はインターフェイスを使用しているので、カスタムデシリアライザを使用してPOSTオブジェクトを読みました。それは最後の数日まで正しく働いた。 しかし、ある日、私は500 - 内部サーバーのエラーを取得し始めました。 "CreateModelを介してインターフェイスのインスタンスを作成できません"と言っています。その時、私はPostManアプリを使っていました。コードに事実上変化はなかったので、PostMan Appが壊れている可能性があります。

私は確信が持てませんでしたので、Fiddlerで同じクエリを試してみましたが、うまくいきました。今、3〜4日後、フィドラーも同じエラーで作業を停止しました。

て掘り後、私は何とか「BindModelは」の実行を開始したActionFilterAttribute前であってもよいことが分かりました。私はそれがいかに可能か確かではない。この状況を克服するための回避策はありますか? マイポストHTTP呼び出しがちょうどJsonFilterのOnActionExecutingメソッドに入っていない

エラーメッセージ:

[MissingMethodException:インタフェースのインスタンスを作成できません。]
System.RuntimeTypeHandle.CreateInstance(...)
System.RuntimeType.CreateInstanceSlow(...)
System.Activator.CreateInstance(...)
System.Activator.CreateInstance(...)
System.Web.Mvc.DefaultModelBinder.CreateMod el(...)

[MissingMethodException:インタフェースのインスタンスを作成できません。 オブジェクトタイプ 'MyCommonObj.IMyInterface'。]
System.Web.Mvc.DefaultModelBinder.CreateModel(...)
System.Web.Mvc.DefaultModelBinder.BindComplexModel(...)
System.Web.Mvc。 DefaultModelBinder.BindModel(...)

コードスニペット:常に実行モデルバインダー後

public class JsonFilter : ActionFilterAttribute { 
    public string Parameter { get; set; } 
    public Type JsonDataType { get; set; } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) { 
     if (filterContext.HttpContext.Request.ContentType.Contains("application/json")) { 
      string inputContent; 
      filterContext.HttpContext.Request.InputStream.Position = 0; 
      using (var sr = new StreamReader(filterContext.HttpContext.Request.InputStream)) { 
       inputContent = sr.ReadToEnd(); 
      }; 

      var jsonSerializerSettings = new JsonSerializerSettings() { 
       TypeNameHandling = TypeNameHandling.All 
      }; 

      if (JsonDataType == typeof(MyClass)) { 
       var result = JsonConvert.DeserializeObject<MyClass>(inputContent, jsonSerializerSettings); 
       filterContext.ActionParameters[Parameter] = result; 
      } 
      else { 
       throw new NotImplementedException(); 
      } 
     } 
    } 
} 

[HttpPost] 
[JsonFilter(Parameter = "config", JsonDataType = typeof(MyClass))] 
public ActionResult ExecuteApi(MyClass config) { 
    var result = DoSomething(config); 
    return Json(result); 
} 

public interface IMyInterface { 
    string GetValue(); 
} 

public class MyDerivedClass : IMyInterface { 
    public string Value { get; set; } 

    public MyDerivedClass(string v) { 
     Value = v; 
    } 

    public string GetValue() { return Value; } 
} 

public class Query { 
    [JsonProperty(TypeNameHandling = TypeNameHandling.All)] 
    public IMyInterface type { get; set; } 

    public Query() {} 
} 

public class MyClass { 
    List<Query> myList { get; set; } 

    public MyClass() {} 
} 

答えて

0

アクションフィルタ。モデルバインダーの前にフィルターを実行する必要がある場合は、IAuthorizationFilterを使用してください。

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)] 
public class JsonFilter : Attribute, IAuthorizationFilter 
{ 
    public string Parameter { get; set; } 
    public Type JsonDataType { get; set; } 

    public void OnAuthorization(AuthorizationContext filterContext) 
    { 
     if (filterContext.HttpContext.Request.ContentType.Contains("application/json")) 
     { 
      string inputContent; 
      filterContext.HttpContext.Request.InputStream.Position = 0; 
      using (var sr = new StreamReader(filterContext.HttpContext.Request.InputStream)) 
      { 
       inputContent = sr.ReadToEnd(); 
      }; 

      var jsonSerializerSettings = new JsonSerializerSettings() 
      { 
       TypeNameHandling = TypeNameHandling.All 
      }; 

      if (JsonDataType == typeof(MyClass)) 
      { 
       var result = JsonConvert.DeserializeObject<MyClass>(inputContent, jsonSerializerSettings); 
       filterContext.ActionParameters[Parameter] = result; 
      } 
      else 
      { 
       throw new NotImplementedException(); 
      } 
     } 
    } 
} 
+0

このアプローチは、JsonDataTypeを読み込み、デシリアライズされた設定オブジェクトをExecuteApi()メソッドに渡す必要があるため、機能しません。また、このメソッドはすべての呼び出しに対して呼び出されます。可能であれば、このメソッド呼び出しを特定のAPIのみに制限したいと考えています。 –

関連する問題