解決
意図したとおりに自動的に機能する 2 つの別個の部分を作成する必要がありました。
したがって、コントローラー アクション プロセスが成功した場合は部分的なビューを返す必要があり、問題が発生した場合は失敗の詳細を含むエラーをスローする必要があります。これにより、クライアント側で常に成功を処理するのではなく、成功と失敗を区別できるようになります。
これを実現するために使用される主要な部分が 2 つあります。
- 何か問題が発生したときにスローされるカスタム例外クラス。これにより、何らかの理由でいつでも発生する可能性がある一般的な例外と、処理に関連するエラー (特に無効なモデル状態) を区別できます。
- カスタム例外をキャッチし、その例外に基づいて結果を準備する例外アクション フィルター。コードからわかるように、カスタム例外はモデル状態エラーに関する情報を保持するため、このフィルターはカスタム HTTP ステータス コードといくつかのテキスト情報を返すことができます。
それでは詳細へ…
外部リンク: このすべての情報 (詳細な説明とすべてのコード) は、私のブログでも入手できます。最新のコード更新は常に公開されます。
カスタム例外クラス
このクラスは2つのことを提供します
- モデル状態エラーと通常の例外を簡単に区別できるようにする
- 後で使用できるいくつかの基本的な機能を提供する
このクラスは、後でカスタム エラー フィルターで使用されます。
public class ModelStateException : Exception
{
public Dictionary<string, string> Errors { get; private set; }
public ModelStateDictionary ModelState { get; private set; }
public override string Message
{
get
{
if (this.Errors.Count > 0)
{
return this.Errors.First().Value;
}
return null;
}
}
private ModelStateException()
{
this.Errors = new Dictionary<string, string>();
}
public ModelStateException(ModelStateDictionary modelState) : this()
{
this.ModelState = modelState;
if (!modelState.IsValid)
{
foreach (KeyValuePair<string, ModelState> state in modelState)
{
if (state.Value.Errors.Count > 0)
{
this.Errors.Add(state.Key, state.Value.Errors[0].ErrorMessage);
}
}
}
}
}
エラーフィルター属性
この属性は、モデル状態エラーがある場合に、HTTP エラー コードに関してクライアントにエラーを返すのに役立ちます。
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class HandleModelStateExceptionAttribute : FilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (filterContext.Exception != null && typeof(ModelStateException).IsInstanceOfType(filterContext.Exception) && !filterContext.ExceptionHandled)
{
filterContext.ExceptionHandled = true;
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.ContentEncoding = Encoding.UTF8;
filterContext.HttpContext.Response.HeaderEncoding = Encoding.UTF8;
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
filterContext.HttpContext.Response.StatusCode = 400;
filterContext.HttpContext.Response.StatusDescription = (filterContext.Exception as ModelStateException).Message;
}
}
}
その後、コントローラー アクションを自分の属性と出来上がりで装飾するだけです。クライアントでコード 400 のエラーが発生し、フィルターに設定した正しい情報が表示されました。次に、この情報がユーザーに表示されます (モデル状態エラーに関連する場合、フォームを有効にするためにユーザーが修正する必要があるフォーム フィールドの情報が表示されます)。
[HandleModelStateException]
public ActionResult AddComment(MyModel data)
{
// check if state is valid
if (!this.ModelState.IsValid)
{
throw new ModelStateException(this.ModelState);
}
// get data from store
return PartialView("Comment", /* store data */ );
}
これにより、コードはモデル状態エラーで再利用可能になり、それらは必要に応じてクライアントに送信されます。
1 つの問題 (現在は解決済み)
ただし、このコードに関連する問題が 1 つあります。エラー アクション フィルタが設定StatusDescription
され、その文字列に Č などの特殊文字が含まれていると、クライアントで問題が発生します。IE を使用しない限り (バージョン 8 を使用しています)。FFとCH表示ゴミ。そのため、エンコーディングを設定しましたが、機能しません。誰かがこの特殊性に対する回避策を持っている場合は、喜んで耳を傾けます。
コンテンツ自体にエラーメッセージが返された場合、すべて問題ありません。エンコーディングは正しく、必要なものは何でも表示できます。