I have an application that was written in vanilla ASP.NET that I would like to port over to ASP.NET MVC.
I, however, am confused about the right place to persist objects. I need to persist for a couple reasons:
I would like all to have a single database connection, wrapped in a "repository" or "manager" style object.
Each user has a user object that needs to be saved on a per-session basis.
Normally, I would say that #1 would be saved as a static item in the Globals.asax that can be hit using Global.Repository or similar.
And I would normally say that #2 should be a property with a session backing store somewhere in the base class of the pages.
Now the reason I am confused is that I have heard that sessions have changed in MVC, and the Global.asax no longer holds the same class. Also, the concept of pages has been removed, so adding a property to the base class of a controller seems... wrong.
What say yall?
Your database would go in a base class for your controllers. This base class should extend Controller, and all your controllers should extend the base class. Here's a little example:
public class BaseController : Controller
{
private AuthServices _auth;
private LogHelper _log;
private Repository _repository;
/// <summary>
/// <see cref="AuthServices"/>
/// </summary>
protected AuthServices Authorization
{
get { return _auth ?? (_auth = new AuthServices()); }
}
/// <summary>
/// <see cref="LogHelper"/>
/// </summary>
protected LogHelper Log
{
get { return _log ?? (_log = new LogHelper()); }
}
/// <summary>
/// <see cref="Repository"/>
/// </summary>
protected Repository Repository
{
get { return _repository ?? (_repository = new Repository()); }
}
}
Notice the lazy instantiation. That allows me to sneak in before running tests and set my private fields with mocks.
As for the session, your User object can still be saved in the session just as in a traditional ASP.NET application. Almost everything is still around (Response, Cache, Session, etc), but some of them have been wrapped with classes from System.Web.Abstractions so that they can be mocked for testing. They all still behave the same way, though you shouldn't use some of them in their traditional role (e.g., don't Response.Redirect, return an ActionResult such as RedirectToRouteResult that performs your redirection).
As for the reasoning behind your questions....
Don't stress on a single db connection. Depending on your implementation it may even be a bad idea, as requests may step on each other. Just open your connex, use it, and dispose/close it when done.
Also, one of the biggest changes that MVC brings is the rejection of the stateful model that traditional ASP.NET attempted to bring to web development. All that framework and viewstate doesn't exist anymore (pay no attention to the man behind the curtain). The less state you hold onto the less complex and more robust your web application is. Try it, you might like it.
If you use sessions I would recommend having a session class, so that you only need to specify the string name once in code and this will give you IntelliSence also.
public static class SessionHandler
{
// User Values
private static string _userID = "UserID";
private static string _userRole = "UserRole";
public static string UserID
{
get
{
if (HttpContext.Current.Session[SessionHandler._userID] == null)
{ return string.Empty; }
else
{ return HttpContext.Current.Session[SessionHandler._userID].ToString(); }
}
set
{ HttpContext.Current.Session[SessionHandler._userID] = value; }
}
public static string UserRole
{
get
{
if (HttpContext.Current.Session[SessionHandler._userRole] == null)
{ return string.Empty; }
else
{ return HttpContext.Current.Session[SessionHandler._userRole].ToString(); }
}
set
{ HttpContext.Current.Session[SessionHandler._userRole] = value; }
}
}
Sessions haven't changed at all in MVC. The GlobalApplication class in Global.asax still exists, too. Pages exist, also, that you would want to refer to a repository in a controller rather than a page. Adding a property to a base controller class is fine; I do it all the time.
You can create a model binder to encapsulate state.
(See Steve Sanderson's mvc book on his shopping cart implementation)
With the model binder, you have access to the controllerContext - which has the HttpContext.
Related
I currently have a custom PrototypingControllerFactory that looks for a custom [Prototype] attribute on the action method being invoked for the current request, and depending on whether the attribute is present or not will inject a different implementation of an interface ISomeService. (In this case ISomeService more or less abstracts a messaging service, so the mock implementation allows returning "canned" results when the real implementation is not yet ready to handle a particular message).
So for example, if I have a controller class like so:
public class MyController : Controller
{
private readonly ISomeService _someService;
public MyController(ISomeService someService /*, .... other dependencies */
{ _someService = someService; //... etc }
public ActionResult Action1()
{
//...
_someService.SomeMethod();
//...
}
[Prototype]
public ActionResult Action2()
{
//...
_someService.SomeMethod();
//...
}
}
Then when Action1 is invoked from an http request, _someService should use the production implementation of ISomeService, but when Action2 is invoked, _someService should have a Mocked version of ISomeService.
From a strict design standpoint, I realize this might point to having too many actions in a particular controller (otherwise, for example, I could just mark an entire controller as having [Prototype]) , but due to project inertia, I would rather not try to force a change in how actions are placed in controllers.
Currently the autofac registration has the following:
builder.RegisterControllers(Assembly.GetExecutingAssembly());
if (ConfigurationManager.AppSettings["AllowPrototyping"] == "true")
{
builder.RegisterType<PrototypingControllerFactory>().As<IControllerFactory>().InstancePerRequest();
}
However, this means that the controller factory has to do some fancy work to figure out constructor arguments, and get instances from the DI container. Recently, I have discovered some subtle differences in behavior between the custom controller factory, and the "real" controller factory that are not desirable.
I would like to eliminate the custom controller factory, and instead have autofac fully handle resolution of the controllers.
How can I tell autofac to resolve a different implementation of an interface depending on whether the currently executing action is decorated with my custom [Prototype] attribute?
The first option depends on reliably being able to determine the controller action method directly from the route data, which is not necessarily straightforward. Part of the issue is that creation of the controller (and hence injection of the dependencies) occurs fairly early in the process, even before authorization filters run.
If some reliable implementation of a magical method say ActionDescriptor GetActionDescriptor(RoutData routeData) actually existed, then I could do something like the following:
builder.Register<ISomeService>(c =>
{
var httpRequest = c.Resolve<HttpRequestBase>();
var actionDescriptor = GetActionDescriptor(httpRequest.RequestContext.RouteData);
if (actionDescriptor.GetAttributes<PrototypeAttribute>().Any())
{
return new PrototypeSomeService();
}
return new RealSomeService();
}).InstancePerRequest();
However the closest I could come to getting an ActionDescriptor at the point where the controller is intantiated was overriding DefaultControllerFactory, which is precisely what I am trying to get away from.
From default controller factory you can use the protected DefaultControllerFactory.GetControllerType() from which you could then create a ReflectedControllerDescriptor. But then you still have to do some munging to get the correct action descriptor from controllerDescriptor.GetCanonicalActions(). (In fact, I suspect this "munging" is leading to the subtle differences in the original custom controller factory). This could get even more complicated when routes are used from other http handlers (think Elmah or MiniProfiler for example).
In the end I opted to avoid attempting to map RouteData to an ActionDescriptor by making [PrototypeAttribute] inherit from ActionFilterAttribute so that I could easily hook into OnActionExecuting, from which point I added an identifier to the current HttpContext, e.g.
public class PrototypeAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.RequestContext.HttpContext.Items.Add("Prototype", "Prototype");
base.OnActionExecuting(filterContext);
}
}
Then I modified my PrototypeSomeService so that it wrapped an implementation of ISomeService and delegated to it if the context did not contain the prototype key, e.g.
public class PrototypeSomeService : ISomeService
{
private readonly ISomeService _wrappedService;
private readonly HttpRequestBase _httpRequest;
public PrototypeSomeService(ISomeService wrappedService, HttpRequestBase httpRequest)
{
_wrappedService = wrappedService;
_httpRequest = httpRequest
}
public object SomeMethod()
{
if(_httpRequest.RequestContext.HttpContext.Items.Contains("Prototype"))
return _wrappedService.SomeMethod();
//other prototype logic...
return prototypeResult;
}
}
The final piece to tie it all together is to use autofac's decorator capabilities:
var someServiceRegistration = builder.RegisterType<SomeService>().InstancePerRequest();
if (ConfigurationManager.AppSettings["AllowPrototyping"] == "true")
{
someServiceRegistration.Named<ISomeService>("Prototype");
builder.RegisterDecorator<ISomeService>(
(c, inner) => new PrototypeSomeService(inner, c.Resolve<HttpRequestBase>()),
fromKey: "Prototype"
);
}
else
{
someServiceRegistration.As<ISomeService>();
}
One small downside is that you have to make sure you use a unique key for the httpcontext item or else strange things will happen, but that is pretty easily avoided by e.g. using a guid.
This approach allowed me to leave most of the existing code unchanged, only modifying the prototype implementation of the service and the autofac registrations.
You can read more about autofac decorators at:
http://nblumhardt.com/2011/01/decorator-support-in-autofac-2-4/
http://docs.autofac.org/en/latest/advanced/adapters-decorators.html?highlight=decorator#decorators
This is more of a design concern.
Im building an app and i have created my Repository Pattern Structure as following :
My Core name space is the DAL/Repository/BusinessLogic layers assembly.
By the way, i am using Dapper.NET micro ORM as my data connection, thats why you will see an extension on my SqlConnection object.
For my data access, i have created a base repository class :
namespace Core
{
public class BaseRepository<T>: IDisposable where T : BaseEntity
{
protected SqlConnection conn = null;
#region Constructors
public BaseRepository() : this("LOCAL")
{
}
public BaseRepository(string configurationKey = "LOCAL")
{
conn = new SqlConnection(ConfigurationManager.ConnectionStrings[configurationKey].ConnectionString);
}
#endregion
#region IDisposable
public void Dispose()
{
conn.Dispose();
}
#endregion
/// <summary>
/// returns a list of entities
/// </summary>
/// <typeparam name="T">BaseEntity type</typeparam>
/// <param name="sproc">optional parameters, stored procedure name.</param>
/// <returns>BaseEntity</returns>
protected virtual IEnumerable<T> GetListEntity(string sproc = null)
{
string storedProcName = string.Empty;
if (sproc == null)
{
storedProcName = "[dbo].sp_GetList_" + typeof(T).ToString().Replace("Core.",string.Empty);
}
else
{
storedProcName = sproc;
}
IEnumerable<T> items = new List<T>();
try
{
conn.Open();
items = conn.Query<T>(storedProcName,
commandType: CommandType.StoredProcedure);
conn.Close();
}
finally
{
conn.Close();
}
return items;
}
}
}
And for each entity that I have, lets say ExtendedUser, Messages , i am creating its on Interface-Class pair like this :
namespace Core
{
public class ExtendedUserRepository : BaseRepository<UsersExtended>,IExtendedUserRepository
{
public ExtendedUserRepository() : this("PROD")
{
}
public ExtendedUserRepository(string configurationKey) : base(configurationKey)
{
}
public UsersExtended GetExtendedUser(string username)
{
var list = GetListEntity().SingleOrDefault(u => u.Username == username);
return list;
}
public UsersExtended GetExtendedUser(Guid userid)
{
throw new NotImplementedException();
}
public List<UsersExtended> GetListExtendedUser()
{
throw new NotImplementedException();
}
}
}
etc.
The above code is just one of the entities :ExtendedUser.
The question is : should i create a Interface-ClassThatImplemenetsInterface pair for each entity that i have ? or should i have only one RepositoryClass and one IRepository interface with all my methods from all of my entities?
I don't think you need to create interface without the reason. I even don't see why you need base repository class here. I even think this is not repository but DAL (Data Access Layer) but this is defintion argue.
I think good DAL implementation should decouple database structure from business logic structure - but hardcoding sp_GetList_XXXEntityNameXXX pattern or passing stored procedure name outside of DAL is not decoupling.
You are very optimistic or your application is really simple if you think all entity lists are obtained in one way and you will always need full set of entities in business logic without any parameters.
Separating interface from implementation is only needed if you plan to replace/wrap out different implementations, or mix few interfaces in one class. Otherwise it is not required.
Don't think in terms of entities when creating repositories. Repository contains business logic and should be built over scenarios of usage. Having classes like you have is more about Data Access Layer - and DAL is built over queries you would need in business logic. Probably you would never need list of ALL users at once - but would very often need list of active users, privileged users etc.
It is really hard to predict what queries you will need - so I prefer to start designing from business logic and add DAL methods by the way.
A system with a complex domain model often benefits from a layer, such
as the one provided by Data Mapper (165), that isolates domain objects
from details of the database access code. In such systems it can be
worthwhile to build another layer of abstraction over the mapping
layer where query construction code is concentrated.
http://martinfowler.com/eaaCatalog/repository.html
With a generic repository you can have common methods like findBy(array('id' => 1)), findOneBy(array('email' => 'john#bar.com')), findById(), findAll() and so on. Indeed, it'll have one interface.
You'll always have to create a concrete implementation that will indicates which is the domain object that will be managed by the repository in order to accomplish this getUsersRepository().findAll()
Moreover, if you need more complicated queries, you can create new methods on the concrete implementation, such as findMostActiveUsers() and then reuse it across your application.
Now, answering your question:
Your application will be expecting for at least one interface (that generic one, with the common methods). But if you manage to have specific methods, like the one I've just mentioned above, you'd be better having another interface (e.g. RepositoryInterface and UsersRepositoryInteface).
With that in mind, then you'll only depend on the repository interface. The query construction will be encapsulated by the concrete implementation. So you'll be able to change your repository implementation (e.g. using an full-blow ORM) without affecting the rest of your application.
I know similar questions have been posed before, but I could not find a duplicate that handles ASP.NET MVC (and the controller aspect) specifically.
My question is as follows:
In a MVC model, my understanding is that the controller should handle the use of HttpContext to determine who is logged on, if any. This is so the controller can present this information to the view, so that the view itself does not have to perform these look-ups.
Is there any defacto standard on how to do it?
My current setup is as follows [simplified]
I have a BaseController, which all my other controllers inherit.
In BaseController, I perform the following override:
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
base.Initialize(requestContext);
ViewData["IsUserLoggedIn"] = IsUserLoggedIn; // bool property checking HttpContext.User.Identity.IsAuthenticated;
ViewData["CurrentUser"] = CurrentUser; // Property returning logged in user, or null.
}
Then, naturally, in my Views I can check the ViewData values.
How do you do it? I'd like to know if something is wrong with my setup, and if so, what's wrong? I'm not 100% comfortable with my solution, - mainly because I'm not too familiar with the cycle, and I'm uncertain whether I've placed my code at the correct place.
I'm aware there might not be "one answer binds them all" here, I'm accepting the answer that offers most insight.
I put an encrypted element into a cookie usually. That element can be anything, but I generally make it the username.
Then in Global.asax.cs I implement Application_AuthenticateRequest. Each time a page is loaded this method is called by the system. In that method I check the cookie, if it exists, I try to load up the user. If the user loads successfully, then I know I have a logged in user, and I set the current Threads current Principal property to that user.
Once the CurrentPrincipal is set on the current thread you can access that user from your Controller, your View, your Business Layer, anywhere in your execution path.
If I can't use cookies for some reason, then I'll pass it across in ViewData (again encrypted just in case), and store it in hidden variables. Then when Controller::OnActionExecuting runs I do the same work I typically did in AuthenticateRequest (i.e. load the user and put it on the thread).
I have a BaseController class that all my controllers inherit from. It has a "CurrentUser" property that is stored in the session. The full code for my controller has a little more logic for retrieving the user, but this is the basic idea.
public class BaseController : Controller
{
User _currentUser = null;
public User CurrentUser
{
get
{
if (_currentUser == null)
_currentUser = (User)HttpContext.Session["CurrentUser"];
return _currentUser;
}
set
{
_currentUser = value;
HttpContext.Session["CurrentUser"] = value;
}
}
}
}
My models all inherit from a BaseModel class which also has a CurrentUser property.
public class BaseModel
{
public User CurrentUser { get; set; }
}
public class HomeIndexData : BaseModel
{
}
Then my controllers pass the user to the model which allows me to have strongly-typed views.
[HttpGet]
public ActionResult Index()
{
HomeIndexData data = new HomeIndexData();
data.CurrentUser = this.CurrentUser;
return View(data);
}
With this technique, I can also have a strongly-typed master page using BaseModel.
<%# Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage<BaseModel>" %>
I am castle Windsor and it works great for controller constructors in passing in the repository that is being used.
private IStoryRepository Repository;
public StoryController(IStoryRepository Repository)
{
this.Repository = Repository;
}
Now I have an Action that is in the admin area to display the main admin menu. I have used a custom authorisation attribute which will just check that the logged in user is an admin (just an isAdmin flag in the users table)
[AdminAuthorize]
public ActionResult Menu()
private IStoryRepository Repository;
/// <summary>
/// Initializes a new instance of the <see cref="AdminAuthorizeAttribute"/> class.
/// </summary>
public AdminAuthorizeAttribute(IStoryRepository Repository)
{
this.Repository = Repository;
}
/// <summary>
/// Checks if the user is authorised
/// </summary>
/// <param name="httpContext">The HTTP context.</param>
/// <returns>
/// <c>true</c> if authorized; otherwise, <c>false</c>.
/// </returns>
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
return this.Repository.UserIsAdmin(httpContext.User.Identity.Name);
}
How can I get Castle to pass the repository into attribute constructor like it does for a controller constructor?
You basically have two options. Wrap the filter in a proxy, a good example of this can be found here.
Or, within your custom filter you can do an explicit container call. For example using StructureMap (I have no used castle extensively)
ObjectFactory.GetInstance(IStoryRepository)
There may be a third way which is to extend the ActionInvoker to do the injection but I am not sure how this would be done.
The problem is that attributes are constructed by reflection rather than through calls that can be intercepted and replaced with calls that delegate to the container.
There are numerous approaches that can be used to create filters that can support DI, the simplest IMHO is to extend the action invoker and override GetFilters, providing an implementation that uses the attribute to determine the filter type and then resolving that type from the container. An implementation of this approach can be seen in MvcTurbine ( http://mvcturbine.codeplex.com/sourcecontrol/changeset/view/37298?projectName=mvcturbine#758440 ).
Why don't you get the IRepository object from a static factory method inside the Filter constructor? You just use the factory method in a way to allow DI to do its work.
DI will work on your "gateway" method instead of the standard "constructor parameter" approach.
I might be worth looking at FluentMVC project. It allows you to configure attributes at startup and because it uses windsor under the hood should allow for this to be injected pritty easily. For example
FluentMvcConfiguration.Configure = x => {
x.UsingControllerFactory(new WindsorControllerFactory()); x.WithFilter<HandleErrorAttribute>();
x.WithFilter<AuthorizeAttribute>(
Except
.For<AccountController>(ac => ac.LogOn())
.AndFor<AccountController>(ac => ac.LogOn(null, null, false, null))
.AndFor<HomeController>());
};
The code above will add the AuthorizeAttribute to all actions except Login and the home controller
Not sure what the current state of the project is but have used it a few times and works pretty well for me.
Let's say I have an interface like:
interface IThing {
int Id { get; set; }
string Title { get; set; }
}
And in ASP.NET MVC I have a form that posts to a controller action like this:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult NewThing([Bind(Exclude = "Id")] SimpleThing thing) {
// code to validate and persist the thing can go here
}
Where SimpleThing is a concrete class that just barely implements IThing.
However, I would like all my methods to deal with the interface. I have a data assembly that uses NHiberate and its own IThing implementation (let's call it RealThing). I can't pass the SimpleThing to it because it will complain about an "unknown entity".
Does anyone have any ideas about a cleaner way to do this? I was thinking about something along the lines of using a factory class. But how would I get the MVC form binder to use it?
Thanks!
You can use custom model binders. However article on msdn is totally useless. So better to employ search and find something better. There are planaty of articles available.
I came up with two approaches to this.
The first was to add code to my NHibernate Repository class to translate the simple POCO type used by the MVC controller (SimpleThing) to the type of entity that NHibernate wanted (RealThing):
/// <summary>
/// A NHibernate generic repository. Provides base of common
/// methods to retrieve and update data.
/// </summary>
/// <typeparam name="T">The base type to expose
/// repository methods for.</typeparam>
/// <typeparam name="K">The concrete type used by NHibernate</typeparam>
public class NHRepositoryBase<T, K>
: IRepository<T>
where T : class
where K : T, new()
{
// repository methods ...
/// <summary>
/// Return T item as a type of K, converting it if necessary
/// </summary>
protected static K GetKnownEntity(T item) {
if (typeof(T) != typeof(K)) {
K knownEntity = new K();
foreach (var prop in typeof(T).GetProperties()) {
object value = prop.GetValue(item, null);
prop.SetValue(knownEntity, value, null);
}
return knownEntity;
} else {
return (K)item;
}
}
So, any method in the repository can call GetKnownEntity(T item) and it will copy the properties of the item you pass in to the type that NHibernate wants. Obviously this felt a bit clunky, so I looked in to custom model binders.
In the second approach, I created a custom model binder like this:
public class FactoryModelBinder<T>
: DefaultModelBinder
where T : new()
{
protected override object CreateModel(ControllerContext controllerContext,
ModelBindingContext bindingContext,
Type modelType) {
return new T();
}
}
Then I registered that in Global.asax.cs with:
ModelBinders.Binders.Add(typeof(IThing),
new FactoryModelBinder<RealThing>());
And it works fine with a Controller Action that looks like this:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult NewThing([Bind(Exclude = "Id")] IThing thing) {
// code to process the thing goes here
}
I like the second approach, but most of my dependency injection stuff is in the Controller class. I don't like to have to add all these ModelBinder mappings in Global.asax.cs.
There were some good suggestions here and I actually came up with a solution that works. However, I ended up with something altogether. I just created models specific for the form data I was posting and used the default model binder.
Much simpler and it allows me to capture data that isn't part of my domain model (ie. like a "comments" field).
This is not dirrect unswer to your question.
We use slightly different approach to deal with same problem you have. Our Controllers accepts DTOs that match persistent entity field by field. Then we user AutoMapper to create persisten entities that will go to the database. This eliminates unnessesery interfaces and locks down public facing API (means that renaming persistance object's field will not break our client code).