1 // Copyright 2004-2007 Castle Project - http://www.castleproject.org/
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle
.MonoRail
.Framework
18 using System
.Collections
.Generic
;
21 using System
.Reflection
;
22 using System
.Collections
;
23 using System
.Collections
.Specialized
;
25 using Castle
.Components
.Common
.EmailSender
;
26 using Castle
.Components
.Validator
;
27 using Castle
.Core
.Logging
;
28 using Castle
.MonoRail
.Framework
.Configuration
;
29 using Castle
.MonoRail
.Framework
.Helpers
;
30 using Castle
.MonoRail
.Framework
.Internal
;
33 /// Implements the core functionality and exposes the
34 /// common methods for concrete controllers.
36 public abstract class Controller
: IController
41 /// Holds the request/context information
43 internal IRailsEngineContext context
;
46 /// The reference to the <see cref="IViewEngineManager"/> instance
48 internal IViewEngineManager viewEngineManager
;
51 /// Logger instance. Should never be null
53 internal ILogger logger
= NullLogger
.Instance
;
56 /// Holds information to pass to the view
58 private IDictionary bag
= new HybridDictionary();
61 /// The area name which was used to access this controller
63 private string _areaName
;
66 /// The controller name which was used to access this controller
68 private string _controllerName
;
71 /// The view name selected to be rendered after the execution
74 internal string _selectedViewName
;
77 /// The layout name that the view engine should use
79 private string _layoutName
;
82 /// The original action requested
84 private string _evaluatedAction
;
87 /// True if any Controller.Send operation was called.
89 private bool _resetIsPostBack
;
92 /// The helper instances collected
94 internal IDictionary helpers
= null;
97 /// The resources associated with this controller
99 internal ResourceDictionary resources
= null;
102 /// Reference to the <see cref="IResourceFactory"/> instance
104 // internal IResourceFactory resourceFactory;
105 internal IDictionary
<string, IDynamicAction
> _dynamicActions
= new Dictionary
<string, IDynamicAction
>(StringComparer
.InvariantCultureIgnoreCase
);
107 internal bool directRenderInvoked
;
109 internal ControllerMetaDescriptor metaDescriptor
;
111 internal IServiceProvider serviceProvider
;
113 internal ValidatorRunner validator
;
120 /// Constructs a Controller
128 #region Useful Properties
131 /// Gets the view folder -- (areaname +
132 /// controllername) or just controller name -- that this controller
133 /// will use by default.
135 public string ViewFolder
139 if (_areaName
!= null && _areaName
.Length
> 0)
141 return Path
.Combine(_areaName
, _controllerName
);
144 return _controllerName
;
149 /// This is intended to be used by MonoRail infrastructure.
151 public ControllerMetaDescriptor MetaDescriptor
153 get { return metaDescriptor; }
157 /// Gets the actions available in this controller.
159 /// <remarks>It is supposed to be used by MonoRail infrastructure only</remarks>
160 /// <value>The actions.</value>
161 public ICollection Actions
163 get { return metaDescriptor.Actions.Values; }
167 /// Gets a dicitionary of name/<see cref="IResource"/>
169 /// <remarks>It is supposed to be used by MonoRail infrastructure only</remarks>
170 /// <value>The resources.</value>
171 public ResourceDictionary Resources
173 get { return resources; }
177 /// Gets a dictionary of name/helper instance
179 /// <value>The helpers.</value>
180 public IDictionary Helpers
182 get { return helpers; }
186 /// Gets a value indicating whether the request is a post.
189 /// <see langword="true"/> if this request is a post; otherwise, <see langword="false"/>.
193 get { return context.Request.HttpMethod == "POST"; }
197 /// Gets a value indicating whether the request is a get.
200 /// <see langword="true"/> if this request is a get; otherwise, <see langword="false"/>.
204 get { return context.Request.HttpMethod == "GET"; }
208 /// Gets a value indicating whether the request is a put.
211 /// <see langword="true"/> if this request is a put; otherwise, <see langword="false"/>.
215 get { return context.Request.HttpMethod == "PUT"; }
219 /// Gets a value indicating whether the request is a head.
222 /// <see langword="true"/> if this request is a head; otherwise, <see langword="false"/>.
226 get { return context.Request.HttpMethod == "HEAD"; }
230 /// Gets the controller's name.
234 get { return _controllerName; }
238 /// Gets the controller's area name.
240 public string AreaName
242 get { return _areaName; }
246 /// Gets or set the layout being used.
248 public string LayoutName
250 get { return _layoutName; }
251 set { _layoutName = value; }
255 /// Gets the name of the action being processed.
259 get { return _evaluatedAction; }
263 /// Logger for the controller
265 public ILogger Logger
267 get { return logger; }
268 set { logger = value; }
272 /// Gets or sets the view which will be rendered by this action.
274 public string SelectedViewName
276 get { return _selectedViewName; }
277 set { _selectedViewName = value; }
281 /// Gets the property bag, which is used
282 /// to pass variables to the view.
284 public IDictionary PropertyBag
291 /// Gets the context of this request execution.
293 public IRailsEngineContext Context
295 get { return context; }
299 /// Gets the Session dictionary.
301 protected IDictionary Session
303 get { return context.Session; }
307 /// Gets a dictionary of volative items.
308 /// Ideal for showing success and failures messages.
312 get { return context.Flash; }
316 /// Gets the web context of ASP.NET API.
318 protected internal HttpContext HttpContext
320 get { return context.UnderlyingContext; }
324 /// Gets the request object.
326 public IRequest Request
328 get { return Context.Request; }
332 /// Gets the response object.
334 public IResponse Response
336 get { return Context.Response; }
340 /// Shortcut to <see cref="IRequest.Params"/>
342 public NameValueCollection Params
344 get { return Request.Params; }
348 /// Shortcut to <see cref="IRequest.Form"/>
350 public NameValueCollection Form
352 get { return Request.Form; }
356 /// Shortcut to <see cref="IRequest.QueryString"></see>
358 public NameValueCollection Query
360 get { return Request.QueryString; }
364 /// Gets the dynamic actions dictionary.
366 /// Can be used to insert dynamic actions on the controller instance.
369 /// <value>The dynamic actions dictionary.</value>
370 public IDictionary
<string, IDynamicAction
> DynamicActions
372 get { return _dynamicActions; }
376 /// Gets the validator runner instance.
378 /// <value>The validator instance.</value>
379 public ValidatorRunner Validator
381 get { return validator; }
382 set { validator = value; }
386 /// Gets the URL builder instance.
388 /// <value>The URL builder.</value>
389 public IUrlBuilder UrlBuilder
391 get { return (IUrlBuilder) serviceProvider.GetService(typeof(IUrlBuilder)); }
396 /// <see cref="IResponse.IsClientConnected"/>
398 protected bool IsClientConnected
400 get { return context.Response.IsClientConnected; }
404 /// Indicates that the current Action resulted from an ASP.NET PostBack.
405 /// As a result, this property is only relavent to controllers using
406 /// WebForms views. It is placed on the base Controller for convenience
407 /// only to avoid the need to extend the Controller or provide additional
408 /// helper classes. It is marked virtual to better support testing.
410 protected virtual bool IsPostBack
414 if (_resetIsPostBack
) return false;
416 NameValueCollection fields
= Context
.Params
;
417 return (fields
["__VIEWSTATE"] != null) || (fields
["__EVENTTARGET"] != null);
423 #region Useful Operations
426 /// Specifies the view to be processed after the action has finished its processing.
428 /// <param name="name">view template name (the file extension is optional)</param>
429 public void RenderView(string name
)
431 _selectedViewName
= Path
.Combine(ViewFolder
, name
);
435 /// Specifies the view to be processed after the action has finished its processing.
437 /// <param name="name">view template name (the file extension is optional)</param>
438 /// <param name="skipLayout">If set to <c>true</c>, no layout will be used when rendering the view</param>
439 public void RenderView(string name
, bool skipLayout
)
441 if (skipLayout
) CancelLayout();
447 /// Specifies the view to be processed after the action has finished its processing.
449 /// <param name="name">view template name (the file extension is optional)</param>
450 /// <param name="skipLayout">If set to <c>true</c>, no layout will be used when rendering the view</param>
451 /// <param name="mimeType">The mime type to use on the reply</param>
452 public void RenderView(string name
, bool skipLayout
, string mimeType
)
454 if (skipLayout
) CancelLayout();
455 Response
.ContentType
= mimeType
;
461 /// Specifies the view to be processed after the action has finished its processing.
463 /// <param name="controller">Controller name get view from (if you intend to user another controller's view</param>
464 /// <param name="name">view template name (the file extension is optional)</param>
465 public void RenderView(string controller
, string name
)
467 _selectedViewName
= Path
.Combine(controller
, name
);
471 /// Specifies the view to be processed after the action has finished its processing.
473 /// <param name="controller">Controller name get view from (if you intend to user another controller's view</param>
474 /// <param name="name">view template name (the file extension is optional)</param>
475 /// <param name="skipLayout">If set to <c>true</c>, no layout will be used when rendering the view</param>
476 public void RenderView(string controller
, string name
, bool skipLayout
)
478 if (skipLayout
) CancelLayout();
480 RenderView(controller
, name
);
484 /// Specifies the view to be processed after the action has finished its processing.
486 /// <param name="controller">Controller name get view from (if you intend to user another controller's view</param>
487 /// <param name="name">view template name (the file extension is optional)</param>
488 /// <param name="skipLayout">If set to <c>true</c>, no layout will be used when rendering the view</param>
489 /// <param name="mimeType">The mime type to use on the reply</param>
490 public void RenderView(string controller
, string name
, bool skipLayout
, string mimeType
)
492 if (skipLayout
) CancelLayout();
493 Response
.ContentType
= mimeType
;
495 RenderView(controller
, name
);
499 /// Specifies the view to be processed after the action has finished its processing.
501 /// <param name="controller">Controller name get view from (if you intend to user another controller's view</param>
502 /// <param name="name">view template name (the file extension is optional)</param>
503 /// <param name="mimeType">The mime type to use on the reply</param>
504 public void RenderView(string controller
, string name
, string mimeType
)
506 Response
.ContentType
= mimeType
;
508 RenderView(controller
, name
);
512 /// Specifies the view to be processed and results are written to System.IO.TextWriter.
514 /// <param name="output"></param>
515 /// <param name="name">The name of the view to process.</param>
516 public void InPlaceRenderView(TextWriter output
, string name
)
518 viewEngineManager
.Process(output
, Context
, this, Path
.Combine(ViewFolder
, name
));
522 /// Specifies the shared view to be processed after the action has finished its
523 /// processing. (A partial view shared
524 /// by others views and usually in the root folder
525 /// of the view directory).
527 public void RenderSharedView(string name
)
529 _selectedViewName
= name
;
533 /// Specifies the shared view to be processed after the action has finished its
534 /// processing. (A partial view shared
535 /// by others views and usually in the root folder
536 /// of the view directory).
538 public void RenderSharedView(string name
, bool skipLayout
)
540 if (skipLayout
) CancelLayout();
542 RenderSharedView(name
);
546 /// Specifies the shared view to be processed and results are written to System.IO.TextWriter.
547 /// (A partial view shared by others views and usually in the root folder
548 /// of the view directory).
550 /// <param name="output"></param>
551 /// <param name="name">The name of the view to process.</param>
552 public void InPlaceRenderSharedView(TextWriter output
, string name
)
554 viewEngineManager
.Process(output
, Context
, this, name
);
558 /// Cancels the view processing.
560 public void CancelView()
562 _selectedViewName
= null;
566 /// Cancels the layout processing.
568 public void CancelLayout()
574 /// Cancels the view processing and writes
575 /// the specified contents to the browser
577 public void RenderText(string contents
)
581 Response
.Write(contents
);
585 /// Cancels the view processing and writes
586 /// the specified contents to the browser
588 public void RenderText(string contents
, params object[] args
)
590 RenderText(String
.Format(contents
, args
));
594 /// Cancels the view processing and writes
595 /// the specified contents to the browser
597 public void RenderText(IFormatProvider formatProvider
, string contents
, params object[] args
)
599 RenderText(String
.Format(formatProvider
, contents
, args
));
603 /// Sends raw contents to be rendered directly by the view engine.
604 /// It's up to the view engine just to apply the layout and nothing else.
606 /// <param name="contents">Contents to be rendered.</param>
607 public void DirectRender(string contents
)
611 if (directRenderInvoked
)
613 throw new ControllerException("DirectRender should be called only once.");
616 directRenderInvoked
= true;
618 viewEngineManager
.ProcessContents(context
, this, contents
);
622 /// Returns true if the specified template exists.
624 /// <param name="templateName"></param>
625 public bool HasTemplate(string templateName
)
627 return viewEngineManager
.HasTemplate(templateName
);
630 #region RedirectToRoute
635 /// <param name="routeName">Name of the route.</param>
636 public void RedirectToRoute(string routeName
)
638 Redirect(UrlBuilder
.BuildRouteUrl(Context
.UrlInfo
, routeName
));
644 /// <param name="routeName">Name of the route.</param>
645 /// <param name="parameters">The parameters.</param>
646 public void RedirectToRoute(string routeName
, IDictionary parameters
)
648 Redirect(UrlBuilder
.BuildRouteUrl(Context
.UrlInfo
, routeName
, parameters
));
654 /// <param name="routeName">Name of the route.</param>
655 /// <param name="parameters">The parameters.</param>
656 public void RedirectToRoute(string routeName
, object parameters
)
658 Redirect(UrlBuilder
.BuildRouteUrl(Context
.UrlInfo
, routeName
, parameters
));
663 #region RedirectToAction
666 /// Redirects to another action in the same controller.
668 /// <param name="action">The action name</param>
669 protected void RedirectToAction(string action
)
671 RedirectToAction(action
, (NameValueCollection
) null);
675 /// Redirects to another action in the same controller.
677 /// <param name="action">The action name</param>
678 /// <param name="queryStringParameters">list of key/value pairs. Each string is supposed
679 /// to have the format "key=value" that will be converted to a proper
680 /// query string</param>
681 protected void RedirectToAction(string action
, params String
[] queryStringParameters
)
683 RedirectToAction(action
, DictHelper
.Create(queryStringParameters
));
687 /// Redirects to another action in the same controller.
689 /// <param name="action">The action name</param>
690 /// <param name="queryStringParameters">Query string entries</param>
691 protected void RedirectToAction(string action
, IDictionary queryStringParameters
)
693 if (queryStringParameters
!= null)
695 Redirect(AreaName
, Name
, TransformActionName(action
), queryStringParameters
);
699 Redirect(AreaName
, Name
, TransformActionName(action
));
704 /// Redirects to another action in the same controller.
706 /// <param name="action">The action name</param>
707 /// <param name="queryStringParameters">Query string entries</param>
708 protected void RedirectToAction(string action
, NameValueCollection queryStringParameters
)
710 if (queryStringParameters
!= null)
712 Redirect(AreaName
, Name
, TransformActionName(action
), queryStringParameters
);
716 Redirect(AreaName
, Name
, TransformActionName(action
));
723 /// Redirects to the referrer action, according to the "HTTP_REFERER" header (<c>Context.UrlReferrer</c>).
725 [Obsolete("Use RedirectToReferrer")]
726 protected void RedirectToReferer()
728 RedirectToReferrer();
732 /// Redirects to the referrer action, according to the "HTTP_REFERER" header (<c>Context.UrlReferrer</c>).
734 protected void RedirectToReferrer()
736 Redirect(Context
.UrlReferrer
);
740 /// Redirects to the site root directory (<c>Context.ApplicationPath + "/"</c>).
742 public void RedirectToSiteRoot()
744 Redirect(Context
.ApplicationPath
+ "/");
748 /// Redirects to the specified URL. All other Redirects call this one.
750 /// <param name="url">Target URL</param>
751 public virtual void Redirect(string url
)
755 context
.Response
.Redirect(url
);
759 /// Redirects to the specified URL.
761 /// <param name="url">Target URL</param>
762 /// <param name="parameters">URL parameters</param>
763 public virtual void Redirect(string url
, IDictionary parameters
)
765 if (parameters
!= null && parameters
.Count
!= 0)
767 if (url
.IndexOf('?') != -1)
769 url
= url
+ '&' + ToQueryString(parameters
);
773 url
= url
+ '?' + ToQueryString(parameters
);
781 /// Redirects to the specified URL.
783 /// <param name="url">Target URL</param>
784 /// <param name="parameters">URL parameters</param>
785 public virtual void Redirect(string url
, NameValueCollection parameters
)
787 if (parameters
!= null && parameters
.Count
!= 0)
789 if (url
.IndexOf('?') != -1)
791 url
= url
+ '&' + ToQueryString(parameters
);
795 url
= url
+ '?' + ToQueryString(parameters
);
803 /// Redirects to another controller and action.
805 /// <param name="controller">Controller name</param>
806 /// <param name="action">Action name</param>
807 public void Redirect(string controller
, string action
)
809 Redirect(UrlBuilder
.BuildUrl(Context
.UrlInfo
, controller
, action
));
813 /// Redirects to another controller and action.
815 /// <param name="area">Area name</param>
816 /// <param name="controller">Controller name</param>
817 /// <param name="action">Action name</param>
818 public void Redirect(string area
, string controller
, string action
)
820 Redirect(UrlBuilder
.BuildUrl(Context
.UrlInfo
, area
, controller
, action
));
824 /// Redirects to another controller and action with the specified paramters.
826 /// <param name="controller">Controller name</param>
827 /// <param name="action">Action name</param>
828 /// <param name="parameters">Key/value pairings</param>
829 public void Redirect(string controller
, string action
, NameValueCollection parameters
)
831 Redirect(UrlBuilder
.BuildUrl(Context
.UrlInfo
, controller
, action
, parameters
));
835 /// Redirects to another controller and action with the specified paramters.
837 /// <param name="area">Area name</param>
838 /// <param name="controller">Controller name</param>
839 /// <param name="action">Action name</param>
840 /// <param name="parameters">Key/value pairings</param>
841 public void Redirect(string area
, string controller
, string action
, NameValueCollection parameters
)
843 Redirect(UrlBuilder
.BuildUrl(Context
.UrlInfo
, area
, controller
, action
, parameters
));
847 /// Redirects to another controller and action with the specified paramters.
849 /// <param name="controller">Controller name</param>
850 /// <param name="action">Action name</param>
851 /// <param name="parameters">Key/value pairings</param>
852 public void Redirect(string controller
, string action
, IDictionary parameters
)
854 Redirect(UrlBuilder
.BuildUrl(Context
.UrlInfo
, controller
, action
, parameters
));
858 /// Redirects to another controller and action with the specified paramters.
860 /// <param name="area">Area name</param>
861 /// <param name="controller">Controller name</param>
862 /// <param name="action">Action name</param>
863 /// <param name="parameters">Key/value pairings</param>
864 public void Redirect(string area
, string controller
, string action
, IDictionary parameters
)
866 Redirect(UrlBuilder
.BuildUrl(Context
.UrlInfo
, area
, controller
, action
, parameters
));
870 /// Creates a querystring string representation of the namevalue collection.
872 /// <param name="parameters">The parameters.</param>
873 /// <returns></returns>
874 protected string ToQueryString(NameValueCollection parameters
)
876 return CommonUtils
.BuildQueryString(Context
.Server
, parameters
, false);
880 /// Creates a querystring string representation of the entries in the dictionary.
882 /// <param name="parameters">The parameters.</param>
883 /// <returns></returns>
884 protected string ToQueryString(IDictionary parameters
)
886 return CommonUtils
.BuildQueryString(Context
.Server
, parameters
, false);
894 /// Extracts the services the controller uses from the context -- which ultimately
895 /// is a service provider.
897 /// <param name="context">The context/service provider.</param>
898 public void InitializeFieldsFromServiceProvider(IRailsEngineContext context
)
900 serviceProvider
= context
;
902 viewEngineManager
= (IViewEngineManager
) serviceProvider
.GetService(typeof(IViewEngineManager
));
904 IControllerDescriptorProvider controllerDescriptorBuilder
= (IControllerDescriptorProvider
)
905 serviceProvider
.GetService( typeof(IControllerDescriptorProvider
) );
907 metaDescriptor
= controllerDescriptorBuilder
.BuildDescriptor(this);
909 ILoggerFactory loggerFactory
= (ILoggerFactory
) context
.GetService(typeof(ILoggerFactory
));
911 if (loggerFactory
!= null)
913 logger
= loggerFactory
.Create(GetType().Name
);
916 this.context
= context
;
922 /// Initializes the state of the controller.
924 /// <param name="areaName">Name of the area.</param>
925 /// <param name="controllerName">Name of the controller.</param>
926 /// <param name="actionName">Name of the action.</param>
927 public void InitializeControllerState(string areaName
, string controllerName
, string actionName
)
929 SetEvaluatedAction(actionName
);
930 _areaName
= areaName
;
931 _controllerName
= controllerName
;
935 /// Sets the evaluated action.
937 /// <param name="actionName">Name of the action.</param>
938 internal void SetEvaluatedAction(string actionName
)
940 _evaluatedAction
= actionName
;
944 /// Gets the service provider.
946 /// <value>The service provider.</value>
947 protected internal IServiceProvider ServiceProvider
949 get { return serviceProvider; }
953 /// Performs the specified action, which means:
955 /// 1. Define the default view name<br/>
956 /// 2. Run the before filters<br/>
957 /// 3. Select the method related to the action name and invoke it<br/>
958 /// 4. On error, execute the rescues if available<br/>
959 /// 5. Run the after filters<br/>
960 /// 6. Invoke the view engine<br/>
962 /// <param name="action">Action name</param>
963 public void Send(string action
)
966 InternalSend(action
, null);
970 /// Performs the specified action with arguments.
972 /// <param name="action">Action name</param>
973 /// <param name="actionArgs">Action arguments</param>
974 public void Send(string action
, IDictionary actionArgs
)
977 InternalSend(action
, actionArgs
);
981 /// Performs the specified action, which means:
983 /// 1. Define the default view name<br/>
984 /// 2. Run the before filters<br/>
985 /// 3. Select the method related to the action name and invoke it<br/>
986 /// 4. On error, execute the rescues if available<br/>
987 /// 5. Run the after filters<br/>
988 /// 6. Invoke the view engine<br/>
990 /// <param name="action">Action name</param>
991 /// <param name="actionArgs">Action arguments</param>
992 protected virtual void InternalSend(string action
, IDictionary actionArgs
)
994 // If a redirect was sent there's no point in
995 // wasting processor cycles
997 if (Response
.WasRedirected
) return;
999 if (logger
.IsDebugEnabled
)
1001 logger
.DebugFormat("InternalSend for action '{0}'", action
);
1004 bool checkWhetherClientHasDisconnected
= ShouldCheckWhetherClientHasDisconnected
;
1006 // Nothing to do if the peer disconnected
1007 if (checkWhetherClientHasDisconnected
&& !IsClientConnected
) return;
1009 IControllerLifecycleExecutor executor
=
1010 (IControllerLifecycleExecutor
) context
.Items
[ControllerLifecycleExecutor
.ExecutorEntry
];
1012 if (!executor
.SelectAction(action
, Name
, actionArgs
))
1014 executor
.PerformErrorHandling();
1021 executor
.ProcessSelectedAction(actionArgs
);
1026 /// Gives a chance to subclasses to format the action name properly
1027 /// <seealso cref="WizardStepPage"/>
1029 /// <param name="action">Raw action name</param>
1030 /// <returns>Properly formatted action name</returns>
1031 internal virtual string TransformActionName(string action
)
1036 private bool ShouldCheckWhetherClientHasDisconnected
1040 MonoRailConfiguration conf
= (MonoRailConfiguration
)
1041 context
.GetService(typeof(MonoRailConfiguration
));
1043 return conf
.CheckClientIsConnected
;
1048 /// To preserve standard Action semantics when using ASP.NET Views,
1049 /// the event handlers in the CodeBehind typically call <see cref="Send(String)"/>.
1050 /// As a result, the <see cref="IsPostBack"/> property must be logically
1051 /// cleared to allow the Action to behave as if it was called directly.
1053 private void ResetIsPostback()
1055 _resetIsPostBack
= true;
1060 #region Action Invocation
1065 /// <param name="action"></param>
1066 /// <param name="actions"></param>
1067 /// <param name="request"></param>
1068 /// <param name="actionArgs"></param>
1069 /// <returns></returns>
1070 protected internal virtual MethodInfo
SelectMethod(string action
, IDictionary actions
,
1071 IRequest request
, IDictionary actionArgs
)
1073 return actions
[action
] as MethodInfo
;
1079 /// <param name="method"></param>
1080 /// <param name="methodArgs"></param>
1081 protected internal virtual void InvokeMethod(MethodInfo method
, IDictionary methodArgs
)
1083 InvokeMethod(method
, context
.Request
, methodArgs
);
1089 /// <param name="method"></param>
1090 /// <param name="request"></param>
1091 /// <param name="methodArgs"></param>
1092 protected internal virtual void InvokeMethod(MethodInfo method
, IRequest request
, IDictionary methodArgs
)
1094 method
.Invoke(this, new object[0]);
1099 #region Lifecycle (overridables)
1102 /// Initializes this instance. Implementors
1103 /// can use this method to perform initialization
1105 protected virtual void Initialize()
1107 IValidatorRegistry validatorRegistry
=
1108 (IValidatorRegistry
) serviceProvider
.GetService(typeof(IValidatorRegistry
));
1110 validator
= CreateValidatorRunner(validatorRegistry
);
1114 /// Performs application-defined tasks associated
1115 /// with freeing, releasing, or resetting unmanaged resources.
1117 public virtual void Dispose()
1122 /// Creates the default validator runner.
1124 /// <param name="validatorRegistry">The validator registry.</param>
1125 /// <returns></returns>
1127 /// You can override this method to create a runner
1128 /// with some different configuration
1130 protected virtual ValidatorRunner
CreateValidatorRunner(IValidatorRegistry validatorRegistry
)
1132 return new ValidatorRunner(validatorRegistry
);
1136 /// Invoked by the view engine to perform
1137 /// any logic before the view is sent to the client.
1139 /// <param name="view"></param>
1140 public virtual void PreSendView(object view
)
1142 if (view
is IControllerAware
)
1144 (view
as IControllerAware
).SetController(this);
1147 if (context
!= null && context
.Items
!= null)
1149 context
.Items
[Constants
.ControllerContextKey
] = this;
1154 /// Invoked by the view engine to perform
1155 /// any logic after the view had been sent to the client.
1157 /// <param name="view"></param>
1158 public virtual void PostSendView(object view
)
1164 #region Email operations
1167 /// Creates an instance of <see cref="Message"/>
1168 /// using the specified template for the body
1170 /// <param name="templateName">
1171 /// Name of the template to load.
1172 /// Will look in Views/mail for that template file.
1174 /// <returns>An instance of <see cref="Message"/></returns>
1175 public Message
RenderMailMessage(string templateName
)
1177 return RenderMailMessage(templateName
, false);
1181 /// Creates an instance of <see cref="Message"/>
1182 /// using the specified template for the body
1184 /// <param name="templateName">
1185 /// Name of the template to load.
1186 /// Will look in Views/mail for that template file.
1188 /// <param name="doNotApplyLayout">If <c>true</c>, it will skip the layout</param>
1189 /// <returns>An instance of <see cref="Message"/></returns>
1190 public Message
RenderMailMessage(string templateName
, bool doNotApplyLayout
)
1192 IEmailTemplateService templateService
= (IEmailTemplateService
)
1193 ServiceProvider
.GetService(typeof(IEmailTemplateService
));
1195 return templateService
.RenderMailMessage(templateName
, Context
, this, doNotApplyLayout
);
1199 /// Attempts to deliver the Message using the server specified on the web.config.
1201 /// <param name="message">The instance of System.Web.Mail.MailMessage that will be sent</param>
1202 public void DeliverEmail(Message message
)
1206 IEmailSender sender
= (IEmailSender
) ServiceProvider
.GetService( typeof(IEmailSender
) );
1208 sender
.Send(message
);
1212 if (logger
.IsErrorEnabled
)
1214 logger
.Error("Error sending e-mail", ex
);
1217 throw new RailsException("Error sending e-mail", ex
);
1222 /// Renders and delivers the e-mail message.
1223 /// <seealso cref="DeliverEmail"/>
1225 /// <param name="templateName"></param>
1226 public void RenderEmailAndSend(string templateName
)
1228 Message message
= RenderMailMessage(templateName
);
1229 DeliverEmail(message
);
1234 internal class EmptyController
: Controller
1236 public EmptyController(IRailsEngineContext context
)
1238 InitializeFieldsFromServiceProvider(context
);