Wednesday, November 23, 2011

Learning MVC: A multi-user application concept.

As a first experiment with MVC framework, I decided to consider the application that has multiple users where each user has some information stored in the local database. I.e. his "To Do List", to which no one else should have access. The problem, then, is to find a way to uniquely identify the user when he logs on (and, on a later stage, to select data that belongs to this user). Here's a bit of a naive first approach.

Create a database to hold the users, with the GUID being the primary key and ID being an identity and autoincremental. I used SQL CE 4.

App_Data -> Add -> New Item -> SQL Server Compact 4.0 Local Database -> dbUsers.sdf

Tables -> Create Table

Create a model from database. Project -> Add New Item -> Data -> ADO.NET Entity Data Model -> modelUsers.edmx -> Add -> Generate From Database -> dbUsers.mdf -> specify the tblUsers table and Finish.

Create a Controller to work with the Users class

Some useful bits of code in the controller:

To create a user

[HttpPost]
public ActionResult Create(tblUser tbluser)
{
if (ModelState.IsValid)
{
db.tblUsers.AddObject(tbluser);
db.SaveChanges();
return RedirectToAction("Index");
}

return View(tbluser);
}

To get user details

public ViewResult Details(int id)
{
tblUser tbluser = db.tblUsers.Single(t => t.UserID == id);
return View(tbluser);
}

Next, I'm going to try and stick some code into the AccountController.cs provided by the MVC application template. I want to insert a new user into my database table when the new user is registered and I want to get the user ID from the database when the user is authenticated successfully. In the future, probably, user ID may not be required at all and I can make the User GUID a primary key.

So that's how it looks in the Register method of the AccountController:

if (createStatus == MembershipCreateStatus.Success)
{
//Insert a user into the database

tblUser user = new tblUser();

MembershipUser mUser = Membership.GetUser(model.UserName);
if (mUser != null)
{
user.UserGUID = mUser.ProviderUserKey.ToString();

using (dbUsersEntities db = new dbUsersEntities())
{
db.tblUsers.AddObject(user);
db.SaveChanges();
}
}

FormsAuthentication.SetAuthCookie(model.UserName, false /* createPersistentCookie */);
return RedirectToAction("Index", "Home");
}

And this is in the LogOn method of the AccountController:

if (Membership.ValidateUser(model.UserName, model.Password))
{
//user is valid, find his ID in the tblUsers
tblUser tbluser;
using (dbUsersEntities db = new dbUsersEntities())
{
MembershipUser mUser = Membership.GetUser(model.UserName);
if (mUser != null)
{
string guid = mUser.ProviderUserKey.ToString();
tbluser = db.tblUsers.Single(t => t.UserGUID == guid);
}
}

FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
&& !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}

And a quick Index view for the UsersController to verify that the users are actually inserted in the database:

@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.UserID)
</td>
<td>
@Html.DisplayFor(modelItem => item.UserGUID)
</td>
</tr>
}

Register a user

And then verify that a user with that ID and GUID is now present in the tblUsers.

The concept looks feasible, now on to refining and improving it.

by . Also posted on my website

No comments: