Всплывающее сообщение Mvc3 с проблемой обработки PostSharp OnException
- У меня возникли проблемы с возвратом всплывающего сообщения в mvc3, когда выдается какое-то исключение.
- Я использую PostSharp в качестве глобальной инфраструктуры AOP, чтобы перехватывать исключения и обрабатывать их, создавая текст всплывающего окна.
- Я расширил ActionResult для пользовательского объекта, который в ExecuteResult реализует метод RenderViewToString, который создает правильный HTML-код для messagePopup.
- MessagePopup отображается на странице, но действие продолжает выполняться само по себе.
Как я могу остановить его от продолжения работы?
Когда это терпит неудачу, я ловлю это глобально в
namespace Aop
{
/// <summary>
/// Handles Aspect Object Programming in all the projects .
/// The attribute is being injected through Shared AssemblyInfo.cs to all the
/// relevant Assemblies in the project.
/// The code of the class is being added to project in compilation time
/// and by that improves the response time quality
/// </summary>
[Serializable]
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class |
AttributeTargets.Method | AttributeTargets.Constructor,
AllowMultiple = true, Inherited = false)]
[MulticastAttributeUsage(MulticastTargets.Method, AllowMultiple = true,
AllowExternalAssemblies = true)]
public sealed class TraceAttribute : OnMethodBoundaryAspect
{
[Inject]
public IReportBLImpl _reportBL { get; set; }
public TraceAttribute() { }
#region Runtime semantics
/// <summary>
/// Handles all exception in all the project Ness.DoarKamuti exceptions
/// </summary>
/// <param name="eventArgs"></param>
public override void OnException(MethodExecutionEventArgs eventArgs)
{
…
DefActionResult res = DefActionResult.Create("~/Views/Shared/MessagePopup.ascx",_report , DefConstants.MessageDesign.PopUp, "messagePopupBody");
eventArgs.ReturnValue = res;
}
}
Чем он строит мой ActionResult, после обработки содержимого сообщения
открытый класс DefActionResult: ActionResult {
public override void ExecuteResult(ControllerContext context)
{
DefJsonResult model = this.ActionModel;
/* If a view name has been specified, render it */
if (!string.IsNullOrEmpty(model.ViewName))
model.ViewHTML = controller.RenderViewToString(model.ViewName, model.ViewModel);
JsonResult res = new JsonResult() { Data = model, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
res.ExecuteResult(context);
}
}
Тогда я строю ответ
public static class MVCExtensions
{
public static string RenderViewToString(this Controller controller, string viewName, object viewData)
{
//Create memory writer
var sb = new StringBuilder();
var memWriter = new StringWriter(sb);
//Create fake http context to render the view
var fakeResponse = new HttpResponse(memWriter);
var fakeContext = new HttpContext(HttpContext.Current.Request, fakeResponse);
var fakeControllerContext = new ControllerContext(
new HttpContextWrapper(fakeContext),
controller.ControllerContext.RouteData,
controller.ControllerContext.Controller);
var oldContext = HttpContext.Current;
HttpContext.Current = fakeContext;
//Use HtmlHelper to render partial view to fake context
var html = new HtmlHelper(new ViewContext(fakeControllerContext,
new FakeView(), controller.ViewData, controller.TempData, memWriter),
new ViewPage());
html.ViewDataContainer.ViewData = controller.ViewData;
html.RenderPartial(viewName, viewData);
//Restore context
//HttpContext.Current = oldContext;
//Flush memory and return output
memWriter.Flush();
return sb.ToString();
}
После возвращения моего всплывающего сообщения, как и должно быть, оно продолжает исходное действие, как если бы оно не было разрушено, и, конечно, оно разрушается, потому что источник данных не инициализирован.
Я не хочу обрабатывать ошибки с помощью HandleErrorAttribute, потому что он не такой динамичный, как PostSharp .
Как я могу остановить остатки оригинального запроса? (Замечание, я использую сетку Telerik для mvc, чтобы показать данные.)
1 ответ
Чтобы метод не работал как обычно, используйте args.FlowBehavior.Return. Метод должен делать это уже, если только не существует какого-либо другого механизма, использующего try/catch, но ваш аспект должен применяться сам как самый внешний try/catch. Вам действительно нужно посмотреть свой финальный IL сборки, используя ILSpy (ни один из других декомпиляторов не увидит постшарных изменений в данный момент), тогда вы сможете увидеть, что происходит. Если у вас есть атрибут action, то я уверен, что он как-то связан с ним, поскольку postsharp изменит метод, а атрибут action - нет, поэтому он остается самым внешним контроллером потока. Сначала попробуйте FlowBehavior.