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 as- IDENTITY (1, 1). I haven't tested extensively, but this seems to "just work". Please confirm.
- InsertDateTime- I want this to be set to- DateTime.Nowonly 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 to- DateTime.Nowfor 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-4567to- 8881234567before 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 add- PhoneNumberto 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:
- Usertable in the database - handles Id assignment. Could provide default values for InsertDateTime and UpdateDateTime.
- Userclass - handles validation using- GetRuleViolations()method.
- UserRepositoryclass - abstracts away data persistence functions (get, get all, add, delete, and save).
- UserControllerclass - handles user requests and post attempts (index, details, edit, posted edit, create, posted create, and delete).
- UserFormViewModelclass - provides strongly typed data to view (a- Userobject plus backing data for drop-down menus).
- Views/User/Create.aspxand- Views/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 - UpdateDateTimeand- InsertDateTimefields be assigned in the- UserRepositoryclass or the- Userclass?
- Does it makes sense to call phone number conversion methods (on a - PhoneNumberConverterclass) from the- UserFormViewModel?