Lösung
Ich musste zwei separate Teile schreiben, die automatisch genau wie vorgesehen funktionieren .
Es sollte also eine Teilansicht zurückgeben, wenn der Controller-Aktionsprozess erfolgreich ist, und es sollte einen Fehler mit einigen Fehlerdetails ausgeben, wenn die Dinge nicht in Ordnung sind, so dass die Dinge auf der Client-Seite sowohl Erfolg als auch Fehler unterscheiden würden, anstatt immer den Erfolg zu behandeln.
Es gibt zwei Hauptbestandteile, mit denen dies erreicht wird:
- Eine benutzerdefinierte Ausnahmeklasse die ausgelöst wird, wenn etwas schief läuft, damit wir zwischen allgemeinen Ausnahmen, die jederzeit aus beliebigen Gründen auftreten können, und Fehlern im Zusammenhang mit unserer Verarbeitung (insbesondere ungültiger Modellstatus) unterscheiden können
- Filter für Ausnahmemaßnahmen die unsere benutzerdefinierte Ausnahme abfängt und das Ergebnis auf der Grundlage dieser Ausnahme vorbereitet; Wie Sie aus dem Code ersehen können, wird unsere benutzerdefinierte Ausnahme Informationen über Modellstatusfehler enthalten, so dass dieser Filter in der Lage sein wird, einen benutzerdefinierten HTTP-Statuscode sowie einige Textinformationen zurückzugeben
Nun aber zu den Details...
Externer Link : Alle diese Informationen (ausführliche Erklärungen sowie der gesamte Code) sind auch in meinem Blog verfügbar. Die neuesten Code-Updates werden immer sein dort veröffentlicht .
Benutzerdefinierte Ausnahmeklasse
Diese Klasse bietet zwei Dinge
- die Unterscheidung zwischen Modellstatusfehlern und regulären Ausnahmen zu erleichtern
- einige grundlegende Funktionen bereitstellen, die ich später nutzen kann
Diese Klasse wird später in meinem benutzerdefinierten Fehlerfilter verwendet.
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);
}
}
}
}
}
Attribut Fehlerfilter
Dieses Attribut hilft bei der Rückgabe von Fehlern an den Client in Form von HTTP-Fehlercodes, wenn Modellstatusfehler auftreten.
[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;
}
}
}
Danach habe ich einfach meine Controller-Aktion mit meinem Attribut versehen und voila. Ich habe Fehler auf dem Client mit Code 400 und korrekte Informationen, die ich in meinem Filter festgelegt. Diese Informationen werden dann dem Benutzer angezeigt (wenn es sich um Modellstatusfehler handelt, zeigt es Informationen an, welche Formularfelder der Benutzer ändern sollte, um das Formular gültig zu machen).
[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 */ );
}
Dies macht meinen Code wiederverwendbar mit jedem Modell Zustand Fehler und diese werden an den Client, wie sie sollten gesendet werden.
Ein einziges Problem (ist jetzt gelöst)
Aber es gibt noch ein Problem im Zusammenhang mit diesem Code. Wenn mein Fehleraktionsfilter StatusDescription
und diese Zeichenfolge einige Sonderzeichen wie C enthält, erhalte ich auf dem Client einen Fehler. Es sei denn, ich verwende den IE (ich verwende Version 8). FF und CH zeigen Müll an. Deshalb habe ich Kodierungen eingestellt, aber es funktioniert nicht. Wenn jemand eine Lösung für diese Besonderheit hat, würde ich mich freuen, wenn ich sie hören könnte.
Wenn ich im Inhalt selbst eine Fehlermeldung eingebe, ist alles in Ordnung. Die Kodierung ist korrekt und ich kann anzeigen, was ich will.