I'm working on my first ASP.NET MVC app, and I'm running into a little confusion about creating/updating certain data.
I have a database table User
, a LinqToSql-generated partial class User
, and my own custom partial class User
.
I'm using [Bind(Exclude = "Id, InsertDateTime, UpdateDateTime")]
on my version of User
because I don't want users to edit these fields.
I also have a PhoneNumber
field, which I do want users to edit, but it requires transformation. I store this in the database as 10 numbers, but when I display it to users via the view, I convert it to a readable phone number in the view like this:
string.Format("{0:(###) ###-####}", Convert.ToInt64(Model.User.PhoneNumber)).
The problem is, when the user clicks Save, the phone number will always be in the wrong format. Somewhere, I need to strip out all the non-numeric characters (parentheses, dashes, slashes, and spaces).
Questions
For each of the fields listed below, how do I handle Create and Edit actions?
Id
- I believe this is taken care of automatically by SQL-Server because I have all my Id fields set up asIDENTITY (1, 1)
. I haven't tested extensively, but this seems to "just work". Please confirm.InsertDateTime
- I want this to be set toDateTime.Now
only for Create actions, not for Edit actions. So, where would be the appropriate place to set this value: User, UserController, UserFormViewModel, or something else?UpdateDateTime
- I want this to be set toDateTime.Now
for both Create and Edit actions, but again, where should I put the code that does this assignment?PhoneNumber
- Unlike the three fields above, this one is editable by the user, but it need to gets transformed from(888) 123-4567
to8881234567
before the update can occur. Couple question here: (1) Where is the appropriate place for this transformation? I convert the phone number to "user readable" format in the view, where should I convert it back to "database storage" format? (2) Should I addPhoneNumber
to my[Bind(Exclude...)]
attribute?
Update
From the answers so far, I think clarify a few things, at least for myself.
First of all, here's a list of locations where stuff happens with User
data:
User
table in the database - handles Id assignment. Could provide default values for InsertDateTime and UpdateDateTime.User
class - handles validation usingGetRuleViolations()
method.UserRepository
class - abstracts away data persistence functions (get, get all, add, delete, and save).UserController
class - handles user requests and post attempts (index, details, edit, posted edit, create, posted create, and delete).UserFormViewModel
class - provides strongly typed data to view (aUser
object plus backing data for drop-down menus).Views/User/Create.aspx
andViews/User/Edit.aspx
- generates the html to display a UI to the user by combining static data with dynamic data (which is stored in the view model).
My current thinking is that the responsibility for setting Id
, UpdateDateTime
, and InsertDateTime
conceptually lies with the model. The database is definitely responsible for setting the Id
on insert, but it's still a little unclear to me where the date-time fields should be set. There seem to be two choices: the repository (as suggested by @Aaronaught) or the User
class (which already handles validation).
As for the issue converting the PhoneNumber
between ########## and (###) ###-####, this seem conceptually more like a "view" function. I like @Aaronaught's idea of having a dedicated PhoneNumberConverter
class, and I will probably go with that, but there is still a question of who calls the methods on this class. For this, I'm leaning toward my UserFormViewModel
class.
This leads me to two followup questions...
Followup Questions
Should the
UpdateDateTime
andInsertDateTime
fields be assigned in theUserRepository
class or theUser
class?Does it makes sense to call phone number conversion methods (on a
PhoneNumberConverter
class) from theUserFormViewModel
?