Using Unity with ASP.NET MVC 3 for an object stored in Session - asp.net-mvc-3

I've got an MVC controller that stores an object in Session. Different controller actions retrieve the object from Session, do stuff with it, and save it back.
I'd like to use Unity so that the controller just deals with an interface, but I'm not sure how to achieve this (I'm fairly new to the whole dependency injection thing). Here's some sample code:
public class MyController : Controller
{
[HttpGet]
public ActionResult Index()
{
var state = new State();
// do stuff with state
Session[Key] = state;
return View();
}
[HttpPost]
public ActionResult Change()
{
var state = Session[Key] as State;
// do stuff with state
Session[Key] = state;
return View();
}
}
So basically I want to use IState instead of State. But where/how does Unity inject the concrete implementation? It seems like it can't happen in the constructor, because I only need to instantiate a new object in the Index() action. Is there maybe some magic way I can add a parameter to Index() that Unity can use?

If you want to use Unity you must change your implementation little bit. You must define your controller as:
public class MyController : Controller
{
private IState _state;
public MyController(IState state)
{
_state = state;
}
[HttpGet]
public ActionResult Index()
{
// Fill the state but you cannot change instance!
_state.A = ...;
_state.B = ...;
return View();
}
[HttpPost]
public ActionResult Change()
{
// Fill the state but you cannot change instance!
_state.A = ...;
_state.B = ...;
return View();
}
}
Now you need two additional step. You must use PerSessionLifetime manager for your IState resolving and you must configure Unity to resolve controllers and their dependencies - there is some build in support for resolving in ASP.NET MVC 3.
Unity doesn't provide PerSessionLifetime manager so you must build your own.
public class PerSessionLifetimeManager : LifetimeManager
{
private readonly Guid _key = Guid.NewGuid();
public override object GetValue()
{
return HttpContext.Current.Session[_key];
}
public override void SetValue(object newValue)
{
HttpContext.Current.Session[_key] = newValue;
}
public override void RemoveValue()
{
HttpContext.Current.Session.Remove(_key);
}
}
You can use this lifetime when configuring controller or you can configure extension in unity configuration and define your IState:
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
</configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<alias alias="perSession" type="NamespaceName.PerSessionLifetimeManager, AssemblyName"/>
<alias alias="IState" type="NamespaceName.IState, AssemblyName" />
<alias alias="State" type="NamespaceName.State, AssemblyName" />
<container name="Web">
<register type="IState" mapTo="State" >
<lifetime type="perSession" />
</register>
</container>
</unity>
</configuration>

You might want to do this with an ActionFilter. The ActionFilter could grab the object from session state (instantiating it if needed), and add it to your ActionParameters collection.
public class IncludeStateAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(...)
{
var currentState = filterContext.HttpContext.Session[Key] as State;
if (currentState == null)
{
currentState = new State();
}
filterContext.ActionParameters["state"] = currentState
}
public override void OnActionExecuted(...)
{
filterContext.HttpContext.Session[Key] = filterContext.ActionParameters["state"];
}
}
Then, your Index action looks like this:
[HttpGet]
[IncludeState]
public ActionResult Index(State state)
{
// do stuff with state
return View();
}
The only thing I'm unsure about is where your key comes from.
I realize that this doesn't use Unity, but maybe you don't need it.

Related

BeforeSaveEntity get fired after save

I'm using Breeze with my Web API and I want to add some auditoring on my Entities. So I want to use the BeforeSaveEntityDelegate but when I implement it, it gets fired after the save function...
Here is my Breezecontroller:
[BreezeController]
public class EssController : ApiController
{
private readonly ESSContextProvider _contextProvider;
public EssController(ESSContextProvider contextProvider)
{
_contextProvider = contextProvider;
}
protected bool BeforeSaveEntity(EntityInfo entityInfo)
{
// create audit record and add to your instance of your context
// this.Context.YourAuditEntity.Add(...)
if (entityInfo.EntityState == EntityState.Modified)
{
var auditable = (Entity)entityInfo.Entity;
auditable.UpdatedBy = "jja";
auditable.UpdatedDate = DateTime.Now;
}
return true;
}
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
_contextProvider.BeforeSaveEntityDelegate = BeforeSaveEntity;
return _contextProvider.SaveChanges(saveBundle);
}
[HttpGet]
public string Metadata()
{
return _contextProvider.Metadata();
}
}
So first he execute SaveChanges and then enters BeforeSaveEntity...
I think there is no error in the sequence of calls. When you call _contextProvider.SaveChanges(saveBundle); the ContextProvider's SaveChanges method will call the BeforeSaveEntityDelegate if any, then it will persist the changes and call the AfterSaveEntities delegate.
Take a look a the source code for ContextProvider here https://github.com/IdeaBlade/Breeze/blob/master/Breeze.ContextProvider/ContextProvider.cs . Look for the "OpenAndSave" method inside the class.
Don't confuse your ApiController SaveChanges with ContextProvider's SaveChanges.

How and Where to tell if a ViewComponent has been invoked x times in a view?

I have a ViewComponent that I need to invoke twice only! How and where can I tell the invokations count?
Currently I can use a session but I dislike using session in mvc apps! How may I achieve this?
namespace Partials.Components
{
public class MyComponent : ViewComponent
{
public IViewComponentResult Invoke()
{
Session["invoked"]=(int)Session["invoked"]+1;
var model = new{
Website="Stack Overflow",
Url="www.http://stackoverflow.com"
};
return View("_MyComponent ", model);
}
}
}
and in my view
#Component.Invoke("MyComponent")
<span>Invoked ViewComponent <span>#Session["invoked"]</span> times</span>
You can use TempData. It persists only until the next request.
TempData["invoked"]=(int)TempData["invoked"]+1;
View:
<span>Invoked ViewComponent <span>#TempData["invoked"]</span> times</span>
Note: TempData uses session under the covers.
You can use HttpContext.Items which has the advantage of not using the session. These items are stored and shared per request, which would also fit your objective.
In your viewComponent you can add/retrieve an item as in this.Context.Items["MyComponentInvocationCount"]. Whenever the count is greater than 2 you can just return an empty content with return Content(String.Empty).
You can combine that with an extension method so you can get the count from outside that class:
[ViewComponent(Name = "MyComponent")]
public class MyViewComponent : ViewComponent
{
internal static readonly string ContextItemName = "InvocationCount";
public IViewComponentResult Invoke()
{
this.InvocationCount = this.InvocationCount + 1;
if (this.InvocationCount > 2) return Content(String.Empty);
//return your content here
return Content("Can be invoked");
}
private int InvocationCount
{
get
{
return this.Context.InvocationCount();
}
set
{
this.Context.Items[ContextItemName] = value;
}
}
}
public static class MyViewComponentExtensions
{
public static int InvocationCount(this HttpContext context)
{
var count = context.Items[MyViewComponent.ContextItemName];
return count == null ? 0 : (int)count;
}
}
Then you could use it in a view as follows:
#Component.Invoke("MyComponent")
<span>Invoked ViewComponent <span>#Context.InvocationCount()</span> times</span>
If you add the above lines 3 times in a view, you will see that the third one does not add any content.
EDIT - Using ViewComponentInvoker
I have been exploring how to implement this feature adding a custom ViewComponentInvoker.
I started by adding a new attribute that can be used to decorate ViewComponents so they are limited to a certain number of invocations per request:
public class PerRequestInvocationLimitAttribute: Attribute
{
public int PerRequestInvocationLimit { get; set; }
}
You would then create your view component as usual, the only change being adding this attribute:
[PerRequestInvocationLimit(PerRequestInvocationLimit = 2)]
public class MyViewComponent : ViewComponent
{
//implementation of view component
}
We can then create a custom IViewComponentInvoker that decorates the DefaultViewComponentInvoker.
This custom view component invoker will keep track of the number of
times a view component has been invoked in the current request.
When a view component that has the new attribute is invoked, it will only
really invoke it if the number of invocations is below the limit.
Implementing this view component invoker looks like:
public class LimitedPerRequestViewComponentInvoker : IViewComponentInvoker
{
private readonly IViewComponentInvoker _defaultViewComponentInvoker;
public LimitedPerRequestViewComponentInvoker(IViewComponentInvoker defaultViewComponentInvoker)
{
this._defaultViewComponentInvoker = defaultViewComponentInvoker;
}
public void Invoke(ViewComponentContext context)
{
if (!CanInvokeViewComponent(context)) return;
this._defaultViewComponentInvoker.Invoke(context);
}
public Task InvokeAsync(ViewComponentContext context)
{
if (!CanInvokeViewComponent(context)) return Task.WhenAll();
return this._defaultViewComponentInvoker.InvokeAsync(context);
}
private bool CanInvokeViewComponent(ViewComponentContext context)
{
// 1. Increase invocation count
var increasedCount = context.ViewContext.HttpContext.IncreaseInvocationCount(
context.ViewComponentDescriptor.ShortName);
// 2. check if there is any limit for this viewComponent, if over the limit then return false
var limitAttribute = context.ViewComponentDescriptor.Type
.GetCustomAttributes(true)
.OfType<PerRequestInvocationLimitAttribute>()
.FirstOrDefault();
if (limitAttribute != null && limitAttribute.PerRequestInvocationLimit < increasedCount)
{
return false;
}
// 3. There is no limit set or the limit has not been reached yet
return true;
}
}
It uses some extension methods to set/get the invocation count from HttpContext.Items (That you could also use in your view to get the number of times a view component was invoked)
public static class ViewComponentExtensions
{
public static int InvocationCount(this HttpContext context, string viewComponentName)
{
var count = context.Items[GetHttpContextItemsName(viewComponentName)];
return count == null ? 0 : (int)count;
}
internal static int IncreaseInvocationCount(this HttpContext context, string viewComponentName)
{
var count = context.InvocationCount(viewComponentName);
context.Items[GetHttpContextItemsName(viewComponentName)] = ++count;
return count;
}
private static string GetHttpContextItemsName(string viewComponentName)
{
return string.Format("InvocationCount-{0}", viewComponentName);
}
}
The final piece is to create a new IViewComponentInvokerFactory replacing the default one, so it creates an instance of the new custom view component invoker instead of the default one. You also need to register it on Startup.cs:
public class MyViewComponentInvokerFactory : IViewComponentInvokerFactory
{
private readonly IServiceProvider _serviceProvider;
private readonly ITypeActivatorCache _typeActivatorCache;
private readonly IViewComponentActivator _viewComponentActivator;
public MyViewComponentInvokerFactory(IServiceProvider serviceProvider, ITypeActivatorCache typeActivatorCache, IViewComponentActivator viewComponentActivator)
{
_serviceProvider = serviceProvider;
_typeActivatorCache = typeActivatorCache;
_viewComponentActivator = viewComponentActivator;
}
public IViewComponentInvoker CreateInstance(ViewComponentDescriptor viewComponentDescriptor, object[] args)
{
return new LimitedPerRequestViewComponentInvoker(
new DefaultViewComponentInvoker(_serviceProvider, _typeActivatorCache, _viewComponentActivator));
}
}
//Configure the ViewComponentInvokerFactory in Startup.ConfigureServices
services.AddTransient<IViewComponentInvokerFactory, MyViewComponentInvokerFactory>();
With all these pieces in place, you can use your view component 3 times and you will see how it will be rendered only twice:
#Component.Invoke("MyComponent")
<span>Invoked ViewComponent <span>#Context.InvocationCount("MyComponent")</span> times</span>
I prefer this solution for a few reasons:
It is based on the hooks provided by the new mvc framework.
Does not need changes to your view component, other than adding the attribute that sets the invocation limit.
It works when invoking view component asynchronously.

Use Action method selector to differentiate between Ajax and non-ajax request instead of relying on if(Request.isAjaxRequest)?

I'm following a book called 'Asp.Net MVC4 in Action'. And now at certain point they say, Instead of relying on if statement within our code to check if the request is Ajax or not, we could use an action method selector to differentiate it. And what they have done is create a class AcceptAjaxAttribute with following code
using System;
using System.Reflection;
using System.Web.Mvc;
namespace CustomAjax
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AcceptAjaxAttribute : ActionMethodSelectorAttribute
{
public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
{
return controllerContext.HttpContext.Request.IsAjaxRequest();
}
}
}
and the function in controller which looked like this before
var speaker = _repository.FindSpeaker(id);
if(Request.IsAjaxRequest())
{
return Json(speaker, JsonRequestBehaviour.AllowGet);
}
return View();
has changed to something like this
[AcceptAjax]
public ActionResult Details(int id)
{
var speaker = _repository.FindId(id);
return Json(speaker, JsonRequestBehavior.AllowGet);
}
[ActionName("Details")]
public ActionResult Details_NonAjax(int id)
{
var speaker = _repository.FindId(id);
return View();
}
To be honest I have no idea what is being done or why we created new class and used that[AcceptAjax] thingy. Can someone may be explain it to me.
Before you had one action with an if inside, after the refactoring you have 2 actions each returning a different type of result. The ActionMethodSelectorAttribute is used to select the proper action based on some condition. Since the 2 actions have the same name (Details), ASP.NET MVC will use this attribute to select the one or the other based on whether an AJAX request is being used.
But honestly I don't like this approach at all. You now have 2 actions and have repeated the var speaker = _repository.FindId(id); call twice which is not very DRY. Wouldn't it be better if you had this?
[AcceptAjax]
public ActionResult Details(int id)
{
var speaker = _repository.FindId(id);
return View(speaker);
}
If you are like me and think that this is better, then simply replace this AcceptAjaxAttribute you got from the book with an action filter:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AcceptAjaxAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
{
var result = filterContext.Result as ViewResultBase;
if (result != null && result.Model != null)
{
filterContext.Result = new JsonResult
{
Data = result.Model,
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
}
}
}
The OnActionExecuted method will be invoked after the controller action has finished running and returned some result. Inside this method we verify whether the controller action returned a ViewResultBase (ViewResult or PartialViewResult) and whether a model has been passed. If this is the case we simply replace this result by a JsonResult.
And if you want to avoid decorating all your controller actions with this [AcceptAjax] attribute, you could register it as a global action filter in your ~/App_Start/FilterConfig.cs:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new AcceptAjaxAttribute());
}
}

Why is an item in the ViewBag not propagated to the _Layout page?

I have a SiteNavigation class that is being updated in the Initialize event of my base controller e.g.
[Serializable]
public class SiteNavigation
{
public SiteNavigation()
{
IsSummarySelected = true;
}
public Model.Dtos.Folder[] Folders { get; set; }
public bool IsSummarySelected { get; set; }
}
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
base.Initialize(requestContext);
var siteNavigation = new SiteNavigation();
siteNavigation.Folders = GetMeMyFolders() as Folder[];
ViewBag.SiteNavigation = siteNavigation;
}
and in the controller the IsSummarySelected property is changed to this value.
ViewBag.SiteNavigation.IsSummarySelected = false;
When I access the property in the _Layout file with this line of code, the value is ALWAYS true. It's as if the nav object is being New'd up again and the constructor is setting it to true.
#if (ViewBag.SiteNavigation.IsSummarySelected)
I've tried casting the nav object back to a variable and setting the property that way too, no dice. Any help would be appreciated.
Call me baffled!
Thank you,
Stephen
I just copy pasted your code into my sample mvc project, and changing IsSummarySelected in my action correctly was reflected in the _Layout file. Are you certain your controller's assignment is getting hit, and you're not reassigning it afterwards somewhere else?
Edit: Your issues are an example of why I think it's a bad idea to use ViewBag for anything other than a localized quick fix. Debugging dynamic global objects is no fun. Refactoring suggestion: Make a site Navigation property in your base controller
SiteNavigation siteNavigation;
public SiteNavigation SiteNavigation
{
get
{
return siteNavigation;
}
set
{
siteNavigation = value;
}
}
and replace all references to ViewBag.SiteNavigation with this. Then create a custom WebViewPage and put in it.
public SiteNavigation SiteNavigation
{
get
{
return ((BaseController)ViewContext.Controller).SiteNavigation;
}
}
This won't fix your problem, but now you can just stick breakpoints on the get and set properties of SiteNavigation, and it should be very easy to debug your issue now.
I fill my TempData["SplitterIsCollapsed"] when Filters are invoked then via OnResultExecuting method. Additionally i fetch a property state from my UserContext class, which is registered only once per session: builder.RegisterType().As().CacheInSession(); .
Basic info: I use DependcyInjection!
Assignment of the Filter to the Controller:
Controller:
[LayoutTempData]
public class HomeController : Controller
{
//....
}
FilterAttribute class:
namespace MyProject.Web.Infrastructure.Filters
{
public class LayoutTempDataAttribute : ActionFilterAttribute
{
private readonly IUserContext _userContext;
public LayoutTempDataAttribute()
{
_userContext = DependencyResolver.Current.GetService<IUserContext>();
}
public override void OnResultExecuting(ResultExecutingContext context)
{
if (context.Controller.TempData.ContainsKey("SplitterIsCollapsed"))
context.Controller.TempData["SplitterIsCollapsed"] = _userContext.LayoutInformation.SplitterIsCollapsed;
else
context.Controller.TempData.Add("SplitterIsCollapsed", _userContext.LayoutInformation.SplitterIsCollapsed);
}
}
}
The Splitter part of the _Layout.cshtml looks like:
#{Html.Telerik().Splitter().Name("Splitter1")
.Panes(panes =>
{
panes.Add()
.Size("300px")
.Collapsible(true)
.Collapsed((bool)TempData["SplitterIsCollapsed"])
.Content(<div>asdfasdf</div>);
panes.Add()
.Collapsible(false)
.Scrollable(false)
.Content(<div>content2</div>);
})
.Render();
}

Issues with my MVC repository pattern and StructureMap

I have a repository pattern i created on top of the ado.net entity framework. When i tried to implement StructureMap to decouple my objects, i kept getting StackOverflowException (infinite loop?). Here is what the pattern looks like:
IEntityRepository where TEntity : class
Defines basic CRUD members
MyEntityRepository : IEntityRepository
Implements CRUD members
IEntityService where TEntity : class
Defines CRUD members which return common types for each member.
MyEntityService : IEntityService
Uses the repository to retrieve data and return a common type as a result (IList, bool and etc)
The problem appears to be with my Service layer. More specifically with the constructors.
public PostService(IValidationDictionary validationDictionary)
: this(validationDictionary, new PostRepository())
{ }
public PostService(IValidationDictionary validationDictionary, IEntityRepository<Post> repository)
{
_validationDictionary = validationDictionary;
_repository = repository;
}
From the controller, i pass an object that implements IValidationDictionary. And i am explicitly calling the second constructor to initialize the repository.
This is what the controller constructors look like (the first one creates an instance of the validation object):
public PostController()
{
_service = new PostService(new ModelStateWrapper(this.ModelState));
}
public PostController(IEntityService<Post> service)
{
_service = service;
}
Everything works if i don't pass my IValidationDictionary object reference, in which case the first controller constructor would be removed and the service object would only have one constructor which accepts the repository interface as the parameter.
I appreciate any help with this :) Thanks.
It looks like the circular reference had to do with the fact that the service layer was dependent on the Controller's ModelState and the Controller dependent on the Service layer.
I had to rewrite my validation layer to get this to work. Here is what i did.
Define generic validator interface like below:
public interface IValidator<TEntity>
{
ValidationState Validate(TEntity entity);
}
We want to be able to return an instance of ValidationState which, obviously, defines the state of validation.
public class ValidationState
{
private readonly ValidationErrorCollection _errors;
public ValidationErrorCollection Errors
{
get
{
return _errors;
}
}
public bool IsValid
{
get
{
return Errors.Count == 0;
}
}
public ValidationState()
{
_errors = new ValidationErrorCollection();
}
}
Notice that we have an strongly typed error collection which we need to define as well. The collection is going to consist of ValidationError objects containing the property name of the entity we're validating and the error message associated with it. This just follows the standard ModelState interface.
public class ValidationErrorCollection : Collection<ValidationError>
{
public void Add(string property, string message)
{
Add(new ValidationError(property, message));
}
}
And here is what the ValidationError looks like:
public class ValidationError
{
private string _property;
private string _message;
public string Property
{
get
{
return _property;
}
private set
{
_property = value;
}
}
public string Message
{
get
{
return _message;
}
private set
{
_message = value;
}
}
public ValidationError(string property, string message)
{
Property = property;
Message = message;
}
}
The rest of this is StructureMap magic. We need to create validation service layer which will locate validation objects and validate our entity. I'd like to define an interface for this, since i want anyone using validation service to be completely unaware of the StructureMap presence. Besides, i think sprinkling ObjectFactory.GetInstance() anywhere besides the bootstrapper logic a bad idea. Keeping it centralized is a good way to insure good maintainability. Anyway, i use the decorator pattern here:
public interface IValidationService
{
ValidationState Validate<TEntity>(TEntity entity);
}
And we finally implement it:
public class ValidationService : IValidationService
{
#region IValidationService Members
public IValidator<TEntity> GetValidatorFor<TEntity>(TEntity entity)
{
return ObjectFactory.GetInstance<IValidator<TEntity>>();
}
public ValidationState Validate<TEntity>(TEntity entity)
{
IValidator<TEntity> validator = GetValidatorFor(entity);
if (validator == null)
{
throw new Exception("Cannot locate validator");
}
return validator.Validate(entity);
}
#endregion
}
I'm going to be using validation service in my controller. We could move it to the service layer and have StructureMap use property injection to inject an instance of controller's ModelState to the service layer, but i don't want the service layer to be coupled with ModelState. What if we decide to use another validation technique? This is why i'd rather put it in the controller. Here is what my controller looks like:
public class PostController : Controller
{
private IEntityService<Post> _service = null;
private IValidationService _validationService = null;
public PostController(IEntityService<Post> service, IValidationService validationService)
{
_service = service;
_validationService = validationService;
}
}
Here i am injecting my service layer and validaton service instances using StructureMap. So, we need to register both in StructureMap registry:
ForRequestedType<IValidationService>()
.TheDefaultIsConcreteType<ValidationService>();
ForRequestedType<IValidator<Post>>()
.TheDefaultIsConcreteType<PostValidator>();
That's it. I don't show how i implement my PostValidator, but it's simply implementing IValidator interface and defining validation logic in the Validate() method. All that's left to do is call your validation service instance to retrieve the validator, call the validate method on your entity and write any errors to ModelState.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Exclude = "PostId")] Post post)
{
ValidationState vst = _validationService.Validate<Post>(post);
if (!vst.IsValid)
{
foreach (ValidationError error in vst.Errors)
{
this.ModelState.AddModelError(error.Property, error.Message);
}
return View(post);
}
...
}
Hope i helped somebody out with this :)
I used a similar solution involving a generic implementor of IValidationDictionary uses a StringDictionary and then copied the errors from this back into the model state in the controller.
Interface for validationdictionary
public interface IValidationDictionary
{
bool IsValid{get;}
void AddError(string Key, string errorMessage);
StringDictionary errors { get; }
}
Implementation of validation dictionary with no reference to model state or anything else so structuremap can create it easily
public class ValidationDictionary : IValidationDictionary
{
private StringDictionary _errors = new StringDictionary();
#region IValidationDictionary Members
public void AddError(string key, string errorMessage)
{
_errors.Add(key, errorMessage);
}
public bool IsValid
{
get { return (_errors.Count == 0); }
}
public StringDictionary errors
{
get { return _errors; }
}
#endregion
}
Code in the controller to copy the errors from the dictionary into the model state. This would probably be best as an extension function of Controller.
protected void copyValidationDictionaryToModelState()
{
// this copies the errors into viewstate
foreach (DictionaryEntry error in _service.validationdictionary.errors)
{
ModelState.AddModelError((string)error.Key, (string)error.Value);
}
}
thus bootstrapping code is like this
public static void BootstrapStructureMap()
{
// Initialize the static ObjectFactory container
ObjectFactory.Initialize(x =>
{
x.For<IContactRepository>().Use<EntityContactManagerRepository>();
x.For<IValidationDictionary>().Use<ValidationDictionary>();
x.For<IContactManagerService>().Use<ContactManagerService>();
});
}
and code to create controllers is like this
public class IocControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return (Controller)ObjectFactory.GetInstance(controllerType);
}
}
Just a quick query on this. It's helped me out quite a lot so thanks for putting the answer up, but I wondered which namespace TEntity exists in? I see Colletion(TEntity) needs System.Collections.ObjectModel. My file compiles without anything further but I see your TEntity reference highlighted in Blue which suggests it has a class type, mine is Black in Visual Studio. Hope you can help. I'm pretty keen to get this working.
Have you found any way to seperate validation into the service layer at all? My gut tells me that validating in the Controller is a bit smelly but I've looked high and low to find a way to pass validation error messages back to the controller without tightly coupling the service layer to the controller and can't find anything. :(
Again, thanks for the great post!
Lloyd

Resources