Click here to Skip to main content
15,883,741 members
Articles / Web Development / HTML

Voting Control using MVC5 and Razor

Rate me:
Please Sign up or sign in to vote.
4.71/5 (21 votes)
14 May 2014CPOL3 min read 21.4K   831   26   7
Simple voting control for MVC5 projects, using a partial view

Image 1

Introduction

This is a simple voting control for MVC projects. It is implemented as a partial view, and so can be included wherever required. It was created in Visual Studio 2013 using MVC5.

Background

I originally wrote an article describing a voting control using MVC2. I decided it would be a good idea to update it to use MVC5 and Razor. I started by creating a new ASP.NET web application project in Visual Studio 2013. I opened the original MVC2 project in Visual Studio 2008 (it failed to convert in VS2013) and copied the files across as required. To start with assume that I have done all the changes, and everything works. That way I can show you how to use the code, and see what it looks like. Later in the article I'll describe how it all works and how I ported it from the MVC2 version.

Using the code

In the default Index.aspx page I removed the existing contents of the main div and replaced it with the following:

ASP.NET
<div class="row">
    <div style="float:left">
        @{
            VoteDataModel petModel = (VoteDataModel)ViewData[VoteDataModel.GetViewDataName("Pet")];
            petModel.ControlWidth = 200;
            Html.RenderPartial("VoteControl", petModel);
        }
    </div>
    <p style="width:300px;padding-left:10px;overflow:hidden">
        This is a simple control with a width of 200px. Click on the button to vote,
        or click <b>Skip to Results</b> to see the results without voting.
    </p>
    <div style="clear:both"></div>
    <p>
        This next control has a long question and long answers. The width has been set
        to 400px.
    </p>
    @{
        VoteDataModel longQuestionModel = (VoteDataModel)ViewData[VoteDataModel.GetViewDataName("LongQuestionsAndAnswers")];
        longQuestionModel.ControlWidth = 400;
        Html.RenderPartial("VoteControl", longQuestionModel);
    }
    <p>
        You can get back to the questions by clicking on the <b>Back to Voting</b>
        link, or see the actual number of votes (instead of the percentages) by
        clicking on <b>Show Counts</b>
    </p>
</div>

In this example we are displaying two voting controls. You can see that we specify how the control appears (in this case just the width, but we could add any customisations that we wanted) and where to get the data from. The data - questions, answers and voting counts are all stored in a single XML file.

We need to add a reference to the model namespace at the top of the file:

ASP.NET
@using VoteControlWebApp.Models

The controller (in this case HomeController.cs) needs to be modified in order to create the models:

C#
public ActionResult Index()
{
    VoteDataModel model = new VoteDataModel("Pet", Request.PhysicalApplicationPath + "App_Data\\");
    model.Open();
    ViewData[model.ViewDataName] = model;
    model = new VoteDataModel("LongQuestionsAndAnswers", Request.PhysicalApplicationPath + "App_Data\\");
    model.Open();
    ViewData[model.ViewDataName] = model;

    return View();
} 

The entire page (having voted on both polls) then looks like:

Image 2

So having seen how to use it, lets get back to how I implemented it.

The Voting Control Implementation

The control itself is implemented as a partial view in the Views::Shared folder - VodeControl.cshtml. All the data is passed in as the model - VoteModel.cs in the Models folder.

The XML files containing the data for each instance of the voting control are in the App_Data folder. There is one XML file per voting control instance.

There is a controller - VoteController.cs, in the Controllers folder. It's sole purpose is to process the incoming request when the Vote button is clicked. In order to route the request through to the VoteController, the following route was added to the RouteConfig.cs file:

ASP.NET
routes.MapRoute(
    "VoteButton", // Route name
    "DoVote/{uniqueName}/{voteId}", // URL with parameters
    new { controller = "Vote", action = "DoVote" },
    new { voteId = @"\d{1,3}" } // voteId can only be numeric, and less than 1000
);

The voting control requires a style sheet and javascript (in the Content and Scripts folders), so I added references to them in _Layout.cshtml.

The entire list of files that I had to create or modify is shown below:

Image 3

Under The Hood

The bulk of the code is in the model (as it should be).

The VodelDataModel object contains a list of answers (List<AnswerItem>) and IP addresses (List<IpAddressItem>). There is one AnswerItem for each answer, and one entry is added for each unique client IP address. This is how we make sure the user only votes once. It's not perfect - see the "Points of Interest" in the MVC2 article for more details about this.

The following public methods are available in the model:

static string GetViewDataName(string uniqueName) and string ViewDataName

This gets a name that will be used for the view data. We use this in the controller and in the view - there is a static method that is used in the view, and a instance property that is used in the controller.

C#
public VoteDataModel(string name, string path)

Object constructor.

C#
public bool Open()

Open should always be called after constructing the object. This reads the data from the XML file.

C#
public bool DoVote(int voteId, string ipAddr)

Thread safe - see last section.

This updates the object and the file. Returns true if vote was accepted or false if the ip address was found - i.e., the user has already voted.

C#
public int GetPercentage(int index)

This is used in the partial view to display the percentage.

C#
public int GetBarLength(int index, int controlWidth)

This is used in the partial view to display the percentage bar.

Points of Interest

Converting the code from MVC2 was relatively straightforward. The views required the most work - converting to Razor syntax, and there were some style sheet issues. The model required no modification.

History

  • May 2014 - Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) CodeWrite Ltd.
United Kingdom United Kingdom
Jon is a Software engineer with over 30 years of experience, the last 18 of which have been using C# and ASP.NET. Previously he has used C++ and MFC. He has a degree in Electronic Systems Engineering and is also a fully licensed radio amateur (M0TWM).

Comments and Discussions

 
GeneralMy vote of 5 Pin
dental implant23-Jul-23 6:15
professionaldental implant23-Jul-23 6:15 
Questionit dosnt work Pin
Member 1068874718-Jul-14 20:51
Member 1068874718-Jul-14 20:51 
AnswerRe: it dosnt work Pin
Jonathan Nethercott19-Jul-14 1:39
professionalJonathan Nethercott19-Jul-14 1:39 
AnswerRe: it dosnt work Pin
Jonathan Nethercott20-Jul-14 3:53
professionalJonathan Nethercott20-Jul-14 3:53 
GeneralMy vote of 5 Pin
Volynsky Alex14-May-14 23:51
professionalVolynsky Alex14-May-14 23:51 
GeneralRe: My vote of 5 Pin
Jonathan Nethercott15-May-14 0:08
professionalJonathan Nethercott15-May-14 0:08 
GeneralRe: My vote of 5 Pin
Volynsky Alex15-May-14 0:18
professionalVolynsky Alex15-May-14 0:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.