Could i extension the ModelStateDictionary Class in MVC3 - asp.net-mvc-3

in the ModelStateDictionary class there are only AddModelError and Add function , i want extention the class, add the method like AddModeSuccess,AddModelWarning.
i have a look at the MVC3 source code and found there a lot of thing need add. i don't want to modify the MVC3 code, i just want to add a extention. how could i do?
public void Add(KeyValuePair<string, ModelState> item) {
((IDictionary<string, ModelState>)_innerDictionary).Add(item);
}
public void Add(string key, ModelState value) {
_innerDictionary.Add(key, value);
}
public void AddModelError(string key, Exception exception) {
GetModelStateForKey(key).Errors.Add(exception);
}
public void AddModelError(string key, string errorMessage) {
GetModelStateForKey(key).Errors.Add(errorMessage);
}

You could add them as extension methods to the ModelStateDictionary class:
public static class ModelStateExtensions
{
public static void AddModelSuccess(this ModelStateDictionary modelState, ... some parameters)
{
...
}
public static void AddModelWarning(this ModelStateDictionary modelState, ... some parameters)
{
...
}
}

Related

Invalid void error and illegal modifier error

I keep getting this error:
Illegal modifier for the local class myWebClient; only abstract or final is permitted.
and this error:
void is an invalid type for the variable backButtonClicked
Heres the code where the error occurs.
public class myWebClient extends WebViewClient
{
}
public void backButtonClicked(View view)
{
if (ourBrow.canGoBack())
ourBrow.goBack();
}
public void forwardButtonClicked(View view)
{
if (ourBrow.canGoForward())
ourBrow.goForward();
}
public void goButtonClicked(View view)
{
String theWebsite = Url.getText().toString();
if(theWebsite != null)
ourBrow.loadUrl(theWebsite);
}
public void refreshButtonClicked(View view)
{
ourBrow.reload();
}
Remove the public modifier of the class and put all methods inside the body of the class:
class myWebClient extends WebViewClient
{
public void backButtonClicked(View view)
{
if (ourBrow.canGoBack())
ourBrow.goBack();
}
public void forwardButtonClicked(View view)
{
if (ourBrow.canGoForward())
ourBrow.goForward();
}
public void goButtonClicked(View view)
{
String theWebsite = Url.getText().toString();
if(theWebsite != null)
ourBrow.loadUrl(theWebsite);
}
public void refreshButtonClicked(View view)
{
ourBrow.reload();
}
}

AjaxLink updateAjaxAttributes - AjaxCallListener getPrecondition

I stucked during migration from Wicket 1.5 to 6.6.
Earlier AjaxLink allowed to override getAjaxCallDecorator() method and wrap the script with preDecorateScript(CharSequence script).
Now recommended way is using AjaxCallListener with getPrecondition(Component component) method. But how can I wrap the source script using Component component parameter?
Dont know if i understand you correctly. We do it this way:
public class MyAjaxCallListener implements IAjaxCallListener{
#Override
public CharSequence getBeforeHandler(Component component) {
return null;
}
#Override
public CharSequence getPrecondition(Component component) {
return YOUR_SCRIPT;
}
// ... not needed overrides can return null
}
Then you add it through an Behavior to your AjaxLink.
ajaxLink.add(new AjaxEventBehavior("onclick") {
#Override
protected void onSubmit(AjaxRequestTarget target) {
//do stuff
}
#Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
attributes.getAjaxCallListeners().add(new MyAjaxCallListener());
}
});

How can I intercept all controller calls in an MVC application?

Is there a quick method for intercepting all controller calls in MVC-3?
For logging and testing purposes, I'd like to build a tool that can intercept all controller calls, and log which controller was called, with which message, at what time.
I can't remember where I got this from, but I was looking around for something similar a while back and found an article or something somewhere that contained this logging filter:
public class LogActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Log("OnActionExecuting", filterContext.RouteData);
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
Log("OnActionExecuted", filterContext.RouteData);
}
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
Log("OnResultExecuting", filterContext.RouteData);
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
Log("OnResultExecuted", filterContext.RouteData);
}
private void Log(string methodName, RouteData routeData)
{
var controllerName = routeData.Values["controller"];
var actionName = routeData.Values["action"];
var message = string.Format("{0} controller: {1} action: {2}", methodName, controllerName, actionName);
Debug.WriteLine(message, "Action Filter Log");
}
}
To use it, just add it to the global filters in global.asax:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new LogActionFilter());
}
I'll have a look now to see if I can find the source.
Edit: Found it. It was from this question.
Depending on how big the site is already, you could create a class in the hierarchy between the framework's Controller class and your main controllers.
Something like
public class MyBaseController : Controller {
protected override void OnActionExecuting(ActionExecutingContext filterContext) {
// your logging stuff here
base.OnActionExecuting(filtercontext);
}
}
Then the rest of your controllers can inherit from this, e.g.
public class HomeController : MyBaseController {
// action methods...
}
You can use your own controller factory and register it as well:
From: (many example on the net - insert logging where you want)
adapted from: http://www.keyvan.ms/custom-controller-factory-in-asp-net-mvc
using System;
using System.Configuration;
using System.Web.Mvc;
using System.Web.Routing;
namespace IControllerFactorySample.ControllerFactories
{
public class YourControllerFactory : IControllerFactory
{
#region IControllerFactory Members
public IController CreateController(RequestContext requestContext, string controllerName)
{
if (string.IsNullOrEmpty(controllerName))
throw new ArgumentNullException("controllerName");
IController controller = Activator.CreateInstance(Type.GetType(controllerName)) as IController;
return controller;
}
public void ReleaseController(IController controller)
{
if (controller is IDisposable)
(controller as IDisposable).Dispose();
else
controller = null;
}
#endregion
}
}
dont forget to register it in global.asax.cs
ControllerBuilder.Current.SetControllerFactory(
typeof(YourControllerFactory));
there is a routing debugger developed by Phil Haack
ASP.Net Routing Debugger

MVC3, Unity Framework and Per Session Lifetime Manager Issue

In a simple word I try to create Lifetime manager for Unity framework by using Http Session in my MVC3 project. My sample implementation of lifetime manager is:
public class UnityPerSessionLifetimeManager : LifetimeManager
{
private string sessionKey;
private HttpContext ctx;
public UnityPerSessionLifetimeManager(string sessionKey)
{
this.sessionKey = sessionKey;
this.ctx = HttpContext.Current;
}
public override object GetValue()
{
return this.ctx.Session[this.sessionKey];
}
public override void RemoveValue()
{
this.ctx.Items.Remove(this.sessionKey);
}
public override void SetValue(object newValue)
{
this.ctx.Session[this.sessionKey] = newValue;
}
}
In my global.asax.cs I replaced default controller factory with my own UnityControllerFactory
public class UnityControllerFactory : DefaultControllerFactory
{
private IUnityContainer container;
public UnityControllerFactory(IUnityContainer container)
{
this.container = container;
this.RegisterServices();
}
protected override IController GetControllerInstance(RequestContext context, Type controllerType)
{
if (controllerType != null)
{
return this.container.Resolve(controllerType) as IController;
}
return null;
}
private void RegisterServices()
{
this.container.RegisterType<IMyType, MyImpl>(new UnityPerSessionLifetimeManager("SomeKey"));
}
}
}
I set breakpoints on each function of UnityPerSessionLifetimeManager class, I noticed that when controller factory tries to solve dependencies of my controller, the HttpContext.Session is actually null, so the code fails retrieve from session or save to session.
Any idea why session is null at this stage?
My mistake, I should change code of UnityPerSessionLifetimeManager class to be
public class UnityPerSessionLifetimeManager : LifetimeManager
{
private string sessionKey;
public UnityPerSessionLifetimeManager(string sessionKey)
{
this.sessionKey = sessionKey;
}
public override object GetValue()
{
return HttpContext.Current.Session[this.sessionKey];
}
public override void RemoveValue()
{
HttpContext.Current.Session.Remove(this.sessionKey);
}
public override void SetValue(object newValue)
{
HttpContext.Current.Session[this.sessionKey] = newValue;
}
}
because when the constructor was called to register type, session state is not ready yet and I already assigned http context of that time to a variable. But in later Get/Set functions session state is ready.

Ninject multiple modules

I didnt think this would be a problem originally, but as I keep getting exceptions thought I would post here incase im being an idiot...
I have 2 module classes, one sets up NHibernate and one sets up MVC Controllers, now the problem I have is that I have something like below:
public class NHibernateModule : NinjectModule
{
public override void Load()
{
Bind<ISessionManager>().To<SessionManager>();
}
}
public class ControllerModule : NinjectModule
{
public override void Load()
{
Bind<SomeController>().ToSelf()
.WithConstructorArgument("sessionManager", Kernel.Get<ISessionManager>());
}
}
Whenever I try to use the controller, it just bombs out telling me that its having problems binding the sessionManager argument. I make sure the list has the Nhibernate module in before the Controller module when I create the kernel.
Is there anything immediately stupid in what im doing above?
Assuming:
public class SomeController : Controller
{
private readonly ISessionManager _sessionManager;
public HomeController(ISessionManager sessionManager)
{
_sessionManager = sessionManager;
}
public ActionResult Index()
{
return View();
}
}
The following should be sufficient:
public class NHibernateModule : NinjectModule
{
public override void Load()
{
Bind<ISessionManager>().To<SessionManager>();
}
}
public class ControllerModule : NinjectModule
{
public override void Load()
{
Bind<SomeController>().ToSelf();
}
}
and in Global.asax:
public class MvcApplication : NinjectHttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
protected override void OnApplicationStarted()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
protected override IKernel CreateKernel()
{
var modules = new INinjectModule[]
{
new NHibernateModule(),
new ControllerModule()
};
return new StandardKernel(modules);
}
}

Resources