Tips & Tricks on ASP.NET MVC, Ajax, jQuery, Entity Framework

Pluggable ASP.NET MVC application project structure

Developing loosely coupled modular programs is a good idea because it eliminates the risk of recompilation. This way of development strategy lets you to create modules and deploy it without recompiling the entire project. You will have a main project and multiple modules on top of that. something similar to wordpress core and wordpress plugins does. Here i am explaining,  how to develop a pluggable ASP.NET MVC application project structure.

Step 1

Create a new ASP.NET MVC Project.  This will be our core project and we will be adding different modules to this as needed.  You will see a project structure like this in your solution explorer. Since i opted for the “Empty” project template, the controllers folder is empty.

step1-create-core-project

Step 2

Now let’s create a controller and it’s views to this project. I will add a “Home” controller and it’s “index” action and it’s view. I added some text to the index.cshtml file and when i run the project, we can see the output like this.

step2-add-controller-and-view

Step 3

Our next step is to create a folder for our modules. All of our modules are going to be an area on top of our main(Core) projecct.  So we will create a folder called “Areas” in the Core Project. I have also deleted the “Models” folder and “App_data” folder because we are not using that now.

step3-add-areas-folder

Now if you check the physical location of our Core project, you will see the Areas folder there. We will be using this as the location for our modules.

step3-areas-folder-in-project-location

 

Step 4

Now we will add our first module. Right click on the solution explorer and select Add->New Project from the context menu. You will see the “Add New Project” dialog. Select “ASP.NET MVC4 Web application”. Specify the project name and select the project location same as the path to our Areas folder.

step4-add-module-project

 

This will add the new project to our solution and it will be saved in the “Areas” folder of the main project. If you select the “Areas” folder in the main project and enable the “Show all files” option, you can see that our new project (Forum) is available under the Areas folder.

step5-module-in-areas

Step 6

Our next step is to change the assembly output path location of our module project. Select the Forum project, right click and select properties from the context menu. Go to Build tab. You will see a section called “Output“. There is a property called “Output path” Where you can define where the assemblies of this project should go when we build the project. By default the value will be bin\\ . Change the value to ..\\..\\bin\\ so that it will drop the compiled assemblies to the bin folder of our main project (Core).

step6-set-output-path

Step 7

Now we will inherit the AreaRegistration class and override some items from that. So Let’s add the below class to our module project.

public class ForumAreaRegistration : AreaRegistration
{
    public override string AreaName
    {
        get { return "Forum";  }
    }
    public override void RegisterArea(AreaRegistrationContext context)
    {
        context.MapRoute(
            "forum_default",
            "Forum/{controller}/{action}/{id}",
            new { action = "Index", id = UrlParameter.Optional },
            namespaces: new string[] { "Forum.Controllers" }
        );
    }
}

I will add this class to the App_Start folder of the Forum Project. You can see that we overrode the AreaName property and RegisterArea method in this class. We have provided the area specific routing ( in this case Forum) in the RegisterArea method.

You need to update the RegisterRoutes method of Core project to include the namespace while defining routes. This  is to avoid the conflict between the controllers with same name which exists in both the projects.  So your route defenition (of core project) will looks like this

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
        namespaces: new string[] { "Core.Controllers" }
    );
}

 

Now build your Forum project and then run the main project. You may access the pages from core project and the module and see what it brings.

Page of Core project

Page of Core project

Page from module

Page from module

 

The advantage of this pluggable architecture is, you can make some changes to one of your module and simply drop the assembly for that (and related view files if necessary) to the  bin folder of the main project.

The sample project i created for this blog post is available here for download. Enjoy. Do not forget to say “Hi” to me, if this post was useful to you.

How you should not run a software project

I have been programming for a couple of years now. I worked in teams which delivered ERP level software as well as small team which delivered tiny projects. Other than my regular day job, i usually spend time writing code for my own hobby project(s). I devote time for reading tech blogs and follow a whole bunch of technical experts. The bottom line is, i believe myself that i know some part of this field, software engineering.

There are a lot of people / organizatoins doing software development. Some people doing it in the right way and some does not. I am going to point out some symptoms of  bad ways of developing software here. These are my personal thoughts and it could be absolutely wrong in another persons view. I don’t care what those people think and will definitely try to avoid doing the following  bad practices.

Not Hiring a Designer for your UI/UX development.

If you are not ready to hire a UI developer and you want to build great software, you are thinking it wrong.

User interface obviously play a major role in keeping your end-user happy. It plays a significant role in your conversion rates as well. Nobody wants to use a screen which looks ugly or looks complex. Why did that happen ? because most of the time those were created by the normal developer!

If your company has a UX team, that is great. If not, you should hire someone temporarily who really does the UX job to get the base theme/layout of your app. This layout/theme should include sample pages( HTML & CSS version) for all possible scenarios the app could use. Once the UX designing is done and approved by the upper layer, that should stay as the foundation of all future developments which the programmer does. the dev team lead /manager should make sure that his/her team is strictly following the template defined by the UX team. If there is a requirement to create some page element which was not defined in the base template, the developer should not simply add it himself (unless he is an equally talented designer himself, which is not very common). The request for this new page element should be routed to the UX team and they should handle that.

Remember, if your application is not providing a consistent look and feel, believe me, it is the worst thing. Never do that if you are serious about what you are doing!

Not Providing the developer PC to your programmers

I hate working with slow computers as you do. I loose all my enthusiasm and excitement of writing code if my machine hangs when i build my project.  It is quite frustrating.

You should make sure that your programmers are happy about their computers. It need not be the super computer in the office. But a fairly faster one where they should not feel that it is slow when they run whatever necessary apps they use  for their daily job. If your project is taking more than 6 second to build/rebuild, it is time for an upgrade.  If you are not providing a faster computer to them, you are not only making them frustrated, but bringing additional delay in your project. Remember hardware is much cheaper these days compared to the developer billing.

Faster computers increases productivity. There is  no question about that. If you are an employee and your employer does not understand this, it is time to switch your job.

Reinventing the wheel

This is a debatable point. Should you develop your own libraries when there are similar libraries exist which does a decent job ?. I would not do this unless i am developing such a library to really compete with the existing providers in the market.  What is the purpose of developing another logging framework yourself when log4net and Nlog exists ? These efforts usually ends up in creating a library which may not be perfect as the existing one. One added advantage of the existing libraries are , they are well tested -used by the developer community. so it is reliable.

Reinventing the wheel usually happens with people who are not aware of what is happening in the industry. They are not aware that there is an existing library exist and lot of people in the community is trusting it.  You don’t see them in any community activities.  They are not continuous learners, which is bad for your team.

Creating a project plan which includes Weekends and Late nights

If you are creating a project plan thinking that the developer will work in the weekends and late nights for the delivery,  you are not fit for this job. You are not realizing that the productivity will decrease as the developer works additional time. Jimmy bogard has written a nice article about the 40 hour work culture. you should go and read it.

Remember, a good project manager should be able to mange his people too.

Thinking that the newly hired fresher will deliver same as the experienced senior developer

No!  Big No, is the answer. The newly hired employee can talk whatever he learned in the book and might have convinced you that he would fit for the (fresher) position during the hiring process.  But the knowledge, wisdom of what works better than other,  which the senior developer has acquired during his experience is totally different.  You can not replace that with a newly hired college graduate.

The bottom line is if you are hiring a fresher to replace a senior developer. You are doing it wrong!

 

There are a lot of other miserable things happening in the software development process. These are the few which i came to my mind because unfortunately i happened to experience few of these during my career. Feel free to share your thoughts on this.

Rendering views from custom folders in ASP.NET MVC

ASP.NET MVC works with the concept of Convention over Configuration. that means, the programmer do not need to explicitly do many things and MVC will take care of those if he follows the conventions. One good example is, To return a view, you simply write one line Return View() and it will return the view from the appropriate directory ( assuming the programmer followed the convention and kept the view file in ~/Views/ThatControllerName/ folder with same name as of the action method. but MVC is extensible. If you want to override the convention. you can always do that. This post shows how rendering views from custom folders in asp.net mvc is possible.

By default, you will have a Views folder in root and you can have multiple folders under that with same name as of your controller name. Each of those folder will have views (.cshtml files) for your action methods. so the default structure will look like this for a controller called CustomerController with 3 action methods. index, edit and details.

View directory structure

 

Returning view from a different location

If you want to return a view from a different location, you can do it by specifying the full path to the view file when calling the View method. for example, if you want to return a view (index.cshtml) from a folder called Customer under UI folder which is in the root of the application,  you can do it like this

public ActionResult Index()
{
    return View("~/UI/Customer/Index.cshtml");
}

 

Assuming you have the _viewStart.html and web.config present in your UI folder.

The above method works. but it is not a good solution to hardcode the location like this. What if we have a lots of controllers and action methods ? , are we going to hard code it like this ? No !!!

What we can do is we can extend the razor view engine and tell it to look for views in our custom location.  so if you look at the sourcecode of RazorViewEngine, you can see that the default  location (what the convention follows) is there.

So let’s extend the RazorViewEngine and create our own view engine. Remember that we are going to simply change the View’s default location only. rest of the view functionality is going to be same (as of Razor). So we will create a class which extends from RazorViewEngine class and write code like this.

public class MyCustomViewEngine : RazorViewEngine
{
    public MyCustomViewEngine()
    {
        string[] viewLocationFormatArr=new string[4];
        viewLocationFormatArr[0] = "~/UI/{1}/{0}.cshtml";
        viewLocationFormatArr[1] = "~/UI/{1}/{0}.vbhtml";
        viewLocationFormatArr[2] = "~/UI/Shared/{1}/{0}.vbhtml";
        viewLocationFormatArr[3] = "~/UI/Shared/{1}/{0}.vbhtml";
        this.ViewLocationFormats = viewLocationFormatArr;

        string[] masterLocationFormatArr = new string[4];
        masterLocationFormatArr[0] = "~/UI/{1}/{0}.cshtml";
        masterLocationFormatArr[1] = "~/UI/{1}/{0}.vbhtml";
        masterLocationFormatArr[2] = "~/UI/Shared/{1}/{0}.vbhtml";
        masterLocationFormatArr[3] = "~/UI/Shared/{1}/{0}.vbhtml";
        this.MasterLocationFormats = masterLocationFormatArr;

        string[] partialViewLocationFormatArr = new string[4];
        partialViewLocationFormatArr[0] = "~/UI/{1}/{0}.cshtml";
        partialViewLocationFormatArr[1] = "~/UI/{1}/{0}.vbhtml";
        partialViewLocationFormatArr[2] = "~/UI/Shared/{1}/{0}.vbhtml";
        partialViewLocationFormatArr[3] = "~/UI/Shared/{1}/{0}.vbhtml";
        this.ViewLocationFormats = partialViewLocationFormatArr;

    }
}

Here i updated only the View related things. I did not update the other 3 properties which handles the location for Areas. But it is going to be the same way. You can simply mention the new folder name and it will be fine.

RazorViewEngine class resides in System.Web.Mvc namespace which is in System.Web.Mvc dll

Now what we need to do is to register our new ViewEngine. So let’s go to the global.asax’s Application_Start event, clear existing view engines and register our new one.

protected void Application_Start()
{
    ViewEngines.Engines.Clear();
    var ourViewEngine = new MyCustomViewEngine();
    ViewEngines.Engines.Add(ourViewEngine);

    AreaRegistration.RegisterAllAreas();

    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}

That is all you need to make it happen. Hit F5 and you can see your app is now bringing views from the UI folder, instead of the Views folder.

 

You need to update the _viewStart.cshtml file to update the layout files location as well.

@{
    Layout = "~/UI/Shared/_Layout.cshtml";
}

Hope this helps. Here you can download a sample project which has the above approach implemented. Do not forget to say “Hi” to me, if this post was useful to you. :)

 

Radio button list in ASP.NET MVC

When developing web applications , you may need to show radio button list in ASP.NET MVC  so that users can make a selection from the options(radio buttons) and submit the form.  We can do this easily with the help of MVC Model binding.

Let’s create a quiz page where we are going to show some questions with it’s answers to the user and user can select an answer from the available answer options, represented by radio buttons.

So first we will create some ViewModels for our view. ViewModel is nothing but a POCO class which we will use to transfer data between the action method and the view. So let’s create 3 classes like this.

 

public class Question
{
    public int ID { set; get; }
    public string QuestionText { set; get; }
    public List<Answer> Answers { set; get; }
    public string SelectedAnswer { set; get; }
    public Question()
    {
        Answers = new List<Answer>();
    }
}
public class Answer
{
    public int ID { set; get; }
    public string AnswerText { set; get; }
}
public class Evaluation
{
    public List<Question> Questions { set; get; }
    public Evaluation()
    {
        Questions = new List<Question>();
    }
}

 Now,  in our GET action method for the view, we will create an object of our ViewModel (Evaluation) class and set the Questions and it’s Answers properties and then send that to the view by passing it to the View method.

public ActionResult Index()
{
    var evalVM = new Evaluation();

    //the below is hardcoded for DEMO. you may get the data from some  
    //other place and set the questions and answers

    var q1 = new Question { ID = 1, QuestionText = "What is your favourite language" };
    q1.Answers.Add(new Answer { ID = 12, AnswerText = "PHP" });
    q1.Answers.Add(new Answer { ID = 13, AnswerText = "ASP.NET" });
    q1.Answers.Add(new Answer { ID = 14, AnswerText = "Java" });
    evalVM.Questions.Add(q1);

    var q2 = new Question { ID = 2, QuestionText = "What is your favourite DB" };
    q2.Answers.Add(new Answer { ID = 16, AnswerText = "SQL Server" });
    q2.Answers.Add(new Answer { ID = 17, AnswerText = "MyQL" });
    q2.Answers.Add(new Answer { ID = 18, AnswerText = "Oracle" });
    evalVM.Questions.Add(q2);

    return View(evalVM);           
}

Now our next step is to create the views to render the UI.  We are going to create an editor template to render the questions and it’s answers. So Let’s go to the Views folder and create a folder called EditorTemplates under the current controller folder (if you added the GET action method to Home controller, this will be ~/Views/Home)

Editor template

After creating the folder, Add a new Editor template to that. Right click on the folder and select Add View option and give the name same as the type name (in this case Question).

Now add the below code to the newly created editor template (Question.cshtml)

@model ViewModels.Question
<div>
    @Html.HiddenFor(x=>x.ID)
    <h3> @Model.QuestionText </h3>
    @foreach (var a in Model.Answers)
    {
       <p>
          @Html.RadioButtonFor(b=>b.SelectedAnswer,a.ID)  @a.AnswerText 
       </p>
    }
</div>

What we are doing in the above code is, iterating through each Answers and showing a Radio button and the answer text. We are using the RadioButtonFor html helper method to render the radio button.

Now let’s  go to our main view (index.cshtml) and write some code. Our main view will be strongly typed to our Evaluation viewmodel and we will use the  EditorFor html helper method to bring our editor template to the main view(index.cshtml).

@model ViewModels.Evaluation
<h2>Quiz 24</h2>
@using (Html.BeginForm())
{
    @Html.EditorFor(x=>x.Questions)
    <input type="submit" />
}

now run the app (hit F5) and you will see the screen with the questions and answers. each answer will be accompanied by a radio button so that user can select one.

asp.net mvc radio button list values on form post

Getting the selected radio button values on form post

To get the selected radio button values on form submit, we can check the properties of the posted model. MVC Model binding can bind the posted form data to an instance of our ViewModel. So let’s add the below code to handle the POST action method.

[HttpPost]
public ActionResult Index(Evaluation model)
{
    if (ModelState.IsValid)
    {
        foreach (var q in model.Questions)
        {
            var qId = q.ID;
            var selectedAnswer = q.SelectedAnswer;
            // Save the data 
        }
        return RedirectToAction("ThankYou"); //PRG Pattern
    }
    //to do : reload questions and answers
    return View(model);
}

Now if you run the program and use visual studio break points, you can see that the selected radio button values (AnswerID in our case) is available in the SelectedAnswer property of each question.

 

radio-button-list-in-mvc-getting-selected-value

 

Hope this helps. You can download the sample source code here. Do not forget to say “Hi” to me,  if this post was useful to you.