MVC 4 WebAPI アプリケーションがあります。私がしたいのはModelState
、プット/ポスト中に送信された不正なデータが原因で発生するエラーを除外することです。
が有効ActionFilterAttribute
かどうかをチェックするModelState
があります。状態をErrorMessage
ユーザーに送り返したい。この部分は正常に動作しています。
/// <summary>
/// This filter will validate the models that are used in the webapi
/// </summary>
public class MyValidationFilter :System.Web.Http.Filters.ActionFilterAttribute
{
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
if (!actionContext.ModelState.IsValid)
{
//ErrorResponse is just a simple data structure used to hold response
ErrorResponse errorResponse = new ErrorResponse();
//loop through each key(field) and see if it has any errors
foreach (var key in actionContext.ModelState.Keys)
{
var state = actionContext.ModelState[key];
if (state.Errors.Any())
{
string validationMessage = state.Errors.First().ErrorMessage;
errorResponse.ErrorMessages.Add(new ErrorMessage(validationMessage));
}
}
//this is a custom exception class that i have that sends the response to the user.
throw new WebAPIException(HttpStatusCode.BadRequest, errorResponse );
}
}
}
これらのメッセージを制御できるため、通常の検証 (Required、StringLength、Regex) はすべて正常に機能します。
[Required(ErrorMessage = "ID is required")]
public string ID { get; set; }
ただし、誰かが不適切な形式の XML または JSON データを渡した場合、メッセージを制御できません。もしそうなら、私は得るかもしれません
終了していない文字列。予期される区切り文字: \"。パス ''、行 1、位置 9。
また
プロパティ名を解析した後の無効な文字。':' が予期されていましたが、得られました: }。パス ''、行 1、位置 9。
または私の名前空間を示すこれらのもの。
値 \"Medium\" をタイプ 'MyNameSpace.Tenant.WebAPIs.Library.IndividualRegistrationInfo' に変換中にエラーが発生しました。パス ''、行 1、位置 8。
行 1 の位置 7 にエラーがあります。名前空間 'http://schemas.datacontract.org/2004/07/MyNameSpace.Tenant.WebAPIs.Library.IndividualRegistrationInfo' から要素 'IndividualRegistrationInfo' が必要です..名前が 'asdf' の 'Element' が見つかりました、名前空間 ''
これが発生したときに、どういうわけか一般的な「無効なデータ」メッセージを送り返したいです。私が使用できる別のフィルター、またはこれらのメッセージをキャッチして上書きできる他の場所はありますか?
アップデート
クリスのアドバイスに基づいて私がやったことは次のとおりです。
JSON と XML 用に 2 つの新しい Formatter を作成しました。
public class JsonFormatter : JsonMediaTypeFormatter
{
public override System.Threading.Tasks.Task<object> ReadFromStreamAsync(Type type, System.IO.Stream stream, System.Net.Http.Headers.HttpContentHeaders contentHeaders, IFormatterLogger formatterLogger)
{
System.Threading.Tasks.Task<object> task = base.ReadFromStreamAsync(type, stream, contentHeaders, formatterLogger);
//parse error if null
if (task.Result == null)
{
//handle error here.
}
return task;
}
}
public class XMLFormatter : XmlMediaTypeFormatter
{
public override System.Threading.Tasks.Task<object> ReadFromStreamAsync(Type type, System.IO.Stream stream, System.Net.Http.Headers.HttpContentHeaders contentHeaders, IFormatterLogger formatterLogger)
{
System.Threading.Tasks.Task<object> task = base.ReadFromStreamAsync(type, stream, contentHeaders, formatterLogger);
//parse error if null
if (task.Result == null)
{
//handle error here
}
return task;
}
}
そしてApplication_Start
global.asaxのメソッドで
GlobalConfiguration.Configuration.Formatters.Insert(0, new JsonFormatter());
GlobalConfiguration.Configuration.Formatters.Insert(1, new XMLFormatter());
より良い方法があるかどうかはわかりませんが、これはうまくいくようです。