private void ProcessActionException(IContext context, PageAction action, Exception ex) { XrcUrl errorPage = context.Page.GetPageUrl(action.CatchException.Url.ToLower()); var errorContent = Page(errorPage, new { Exception = ex }, context); // TODO If there is already some content on the stream? An exception can occurs when some content is already written... Think if this is acceptable. context.Response.Write(errorContent.Content); }
private void RenderLayout(IContext childContext, PageAction childAction, Dictionary<string, object> childModules) { XrcResponse currentResponse = childContext.Response; // If a parent is defined call first it using the current response // and defining a SlotCallback event that output the current slot inline. // The event will be called from the layout action by using Cms.Slot(). // Parameters will be also copied from slot to layout. XrcUrl layoutPage = childContext.Page.GetPageUrl(childAction.Layout.ToLower()); Context layoutContext = new Context(new XrcRequest(layoutPage, parentRequest: childContext.Request), currentResponse); layoutContext.CallerContext = childContext; foreach (var item in childContext.Parameters) layoutContext.Parameters.Add(new ContextParameter(item.Name, item.Type, item.Value)); layoutContext.SlotCallback = (s, e) => { var childResult = new StringResult(); using (MemoryStream stream = new MemoryStream()) { XrcResponse response = new XrcResponse(stream, parentResponse: currentResponse); childContext.Response = response; ViewDefinition viewDefinition = childAction.Views[e.Name]; if (viewDefinition != null) ExecuteView(childContext, childAction, viewDefinition, childModules); else throw new ApplicationException(string.Format("Slot '{0}' not found.", e.Name)); childResult.ContentEncoding = response.ContentEncoding; childResult.ContentType = response.ContentType; response.Flush(); stream.Seek(0, SeekOrigin.Begin); using (StreamReader reader = new StreamReader(stream, response.ContentEncoding)) { childResult.Content = reader.ReadToEnd(); } } e.Result = childResult; }; try { ProcessRequest(layoutContext); layoutContext.CheckResponse(); } catch (Exception ex) { // Set a generic status code. We don't want to expose directly parent StatusCode like redirect // otherwise the client is redirected to a wrong page (the parent page). currentResponse.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError; throw new PageException(layoutPage.ToString(), ex); } }
private void ExecuteView(IContext context, PageAction action, ViewDefinition viewDefinition, Dictionary<string, object> modules) { IView view = _viewFactory.Get(viewDefinition.Component, context); try { foreach (var property in viewDefinition.Properties) { object value = _scriptService.Eval(property.Value, modules, context.Parameters); property.PropertyInfo.SetValue(view, value, null); } view.Execute(context); } catch (Exception ex) { if (action.CatchException != null) ProcessActionException(context, action, ex); else throw; } finally { _viewFactory.Release(view); } }