|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
What is PixelDragonsMVC.NET?PixelDragonsMVC.NET is an open source, easy-to-use MVC framework for use with ASP.NET 2.0. It has built-in support for NHibernate and Log4Net and was produced by Pixel Dragons Ltd. to make creating ASP.NET 2.0 applications as easy as possible for us and you. We've created a project on CodePlex. From Wikipedia: "Model-view-controller (MVC) is an architectural pattern used in software engineering. In complex computer applications that present lots of data to the user, one often wishes to separate data (model) and user interface (view) concerns, so that changes to the user interface do not affect the data handling, and that the data can be reorganized without changing the user interface. The model-view-controller solves this problem by decoupling data access and business logic from data presentation and user interaction, by introducing an intermediate component: the controller." See Wikipedia for more information. Sample applicationThe ZIP file above includes a sample application and the full source code of the MVC framework (linked using project references). Follow these instructions:
We have also put our sample project online for you to see. BackgroundWe've tried various MVC frameworks with our ASP.NET applications, but there were always a few things about them that we didn't like. So when the opportunity came up with a new project, we decided to create our own and make it available to everyone. In this article, we talk about NHibernate and assume that the reader has some knowledge of the framework. If you are new to NHibernate, check this out first. Goals of this projectMinimal configurationWe found that there were a lot of unnecessary XML configuration in existing MVC frameworks. We always tried to name our models, view and controllers in a similar way to aid maintenance and make our code understandable and consistent. So we thought it would be cool if the MVC could work out on its own what controller/action/view to use based on the requested URL. Multiple methods (actions) per controllerWe've seen controllers in some of the Java MVCs that support multiple "actions" inside a controller class. This means that the number of class files is reduced and easier to manage, especially for large projects. A controller can then contain all related methods for a particular entity or section of the application. Pass request data via parametersIn one particular framework, data that is posted or on the querystring can be accessed in a controller by creating public properties for each one. So for each piece of data, we had to create a private field and a get/set public property. That's quite a bit of typing if there is a lot of data. We thought it would be better to allow data to be passed to an action method via its parameters. The data should be converted automatically to the correct type, including HttpPostedFile. Built-in support for NHibernateWe've started using NHibernate in our projects and we love it. We wanted the MVC to take care of the session and transactions and provide a generic DAO class that we could use or derive from. We wanted to be able to specify a regular expression and if the action method name matches, the MVC should automatically start a transaction for you and commit/rollback as required at the end of the request. Shared UI source for AJAX and server renderingWith various frameworks, we've been doing various things with Ajax and we've found that a lot of the time we had separate UI code for the same thing depending on whether the server or client was doing the rendering. So we wanted to support a way to use the same UI code that could be used on the server-side or client-side. You can see this in the sample application when paging through contacts. Built-in support for Log4NetWe also wanted the MVC to automatically create and give the controller access to a Log4Net logger, just to try and do as much of the work as possible. With all these things, it means that everything is available in the controller without any extra work. We can just focus on the application. How it worksFor a given request, here are the steps the MVC goes through to make it all work. Code showing what is happening at a given step is included where it is of interest: Step 1: Browser requests an ASHX fileFor example, in the sample application, take a look at default.aspx. It is the start page for the project and redirects to home.ashx. Step 2: PixelDragonsMVC.NET processes the requestTake a look in the web.config file and you will see that PixelDragonsMVC.NET is setup to handle all requests for ASHX files using an HttpHandler. You can change this to any file extension. You just need to change web.config and configure IIS to use ASP.NET to process these files and un-tick the "Check that file exists" option. ASHX is set up like this by default. <httpHandlers>
<remove verb="*" path="*.ashx"/>
<add verb="*" path="*.ashx"
type="PixelDragons.MVC.MVCHandler, PixelDragons.MVC" />
</httpHandlers>
You also need to add the config sections for PixelDragonsMVC.NET: <section name="mvc"
type="PixelDragons.MVC.Configuration.MVCConfigurationHandler," +
" PixelDragons.MVC" />
<mvc mappingFile="mvc.config"
controllerPattern=
"PixelDragons.MVCSample.Controllers.[ControllerName]Controller"
viewWithActionPattern="UI/views/[ControllerName]/[ActionName].aspx"
viewWithNoActionPattern="UI/views/[ControllerName].aspx"
defaultController="PixelDragons.MVC.Controllers.Controller">
<entityAssemblies>
<add name="PixelDragons.MVCSample.Domain" />
</entityAssemblies>
<autoTransactions>
<add regex="^Save.*" type="NewTransaction" />
<add regex="^Delete.*" type="NewTransaction" />
</autoTransactions>
</mvc>
Step 3: Set up NHibernatePixelDragonsMVC.NET creates a <section name="nhibernate"
type="System.Configuration.NameValueSectionHandler,
System, Version=1.0.3300.0,Culture=neutral,
PublicKeyToken=b77a5c561934e089"/>
<nhibernate>
<add key="hibernate.connection.provider"
value="NHibernate.Connection.DriverConnectionProvider"/>;
<add key="hibernate.dialect"
value="NHibernate.Dialect.MsSql2000Dialect"/>
<add key="hibernate.connection.driver_class"
value="NHibernate.Driver.SqlClientDriver"/>
<add key="hibernate.connection.connection_string"
value="server=[YOUR SERVER HERE];" +
"database=[YOUR DATABASE HERE];uid=[YOUR USER ID];" +
"pwd=[YOUR PASSWORD HERE];"/>
</nhibernate>
Step 4: Get controller and action name from requestNext, PixelDragonsMVC.NET works out what the controller and action names are based on the requested file. It looks for the following patterns to match:
It creates a Step 5: TransactionsPixelDragonsMVC.NET can automatically start an NHibernate transaction based on the action name found in step 4. You can set this up in the web.config (see the <autoTransactions>
<add regex="^Save.*" type="NewTransaction" />
<add regex="^Delete.*" type="NewTransaction" />
</autoTransactions>
Step 6: Instantiate the controllerNow that PixelDragonsMVC.NET has the controller name, it tries to create a controller object. First it looks at the <controller name="different"
class="MVCSample.Controllers.Different.AnotherController" />
If there is no mapping for the controller, then PixelDragonsMVC.NET creates the default controller as specified in web.config ( GenericDao<Contact> contactDao = this.PersistenceManager.CreateDao<Contact>();
List<Contact> contacts = contactDao.ListAll();
Step 7: Call the actionNext PixelDragonsMVC.NET calls the If the action method inside the controller class has parameters, PixelDragonsMVC.NET uses reflection to get a list of these and then searches the request for data that has been posted (or on the querystring) by matching the names. It then converts the data to the correct type before passing it into the action method. For example, if the requested file was If the parameter can't be found in the request, the default value for the parameter is used, i.e. object = null, int = 0, etc. The action can then set the model and view to display. Here is an example action that takes data from the request and sets the view and model. Here is what the public void Save(string name, string userId, string password)
{
GenericDao<User> userDao = this.PersistenceManager.CreateDao<User>();
User user = userDao.Create();
user.Name = name;
user.UserId = userId;
user.Password = password;
user = userDao.Store(user);
Session["LoggedInUserUid"] = user.UserUid;
this.ViewName = "saveSuccess";
this.Model = user;
}
Lastly, Step 8: Get the viewIf the action sets a view name, PixelDragonsMVC.NET will look it up in the mapping file for that controller/action. From the mapping, the view can either be rendered directly or redirected to. For the above example, PixelDragonsMVC.NET will render UI/contacts/form.aspx. <views>
<view id="contact-form" path="UI/contacts/form.aspx" />
</views>
<controller name="users">
<action name="save">
<view name="saveSuccess" type="render" ref="contact-form" />
</action>
</controller>
If no view is found matching the name set by the action, then PixelDragonsMVC.NET looks in the shared area. If no view is found in the shared area or the action doesn't set a view name, the default view is rendered. The default view is defined in web.config as Step 9: Complete transactionIf a transaction was created, it is either committed or rolled back depending on if an exception was thrown other than Step 10: Render the view and modelIf the view is to be rendered, the ASPX file is executed on the server and returned to the browser. The model that is set by the controller/action is available to the view for rendering. This keeps the business logic separate from the UI. If the view is a redirect, the browser is redirected to the specified URL. An ASPX view might contain code like this: <%
User user = (User)Context.Items["model"];
%>
...
<input type="text" name="name" id="name" value="<%=user.Name%>" />
Step 11: FinishThe NHibernate session is closed. Feedback and future developmentThis article is a quick overview of how the MVC works. We probably need to create some better documentation and code references, but it's something for you to have a go with at least. As we develop the project, we'll try and improve this. If you have any questions, comments or suggestions, please let us know. We are using this MVC framework in a new project and so will be improving it as and when we find the need. We'll write another article soon with a step-by-step guide of how to create an application that uses our MVC. You can see our other stuff here. History
|
||||||||||||||||||||||