views:

81

answers:

2

I am looking for best practices in applying business logic to form elements in an ASP.NET MVC application. I assume the concepts would apply to most MVC patterns. The goal is to have all the business logic stem from the same place.

I have a basic form with four elements:
Textbox: for entering data
Checkbox: for staff approval
Checkbox: for client approval
Button: for submitting form

The textbox and two check boxes are fields in a database accessed using LINQ to SQL. What I want to do is put logic around the check boxes on who can check them and when.

True table (little silly but it's an example):

  when checked  || may check Staff || may check Client   
 Staff | Client || Staff | Client  ||  Staff | Client 
  0        0    ||   1       0           0        1
  0        1    ||   0       0           0        1
  1        0    ||   1       0           0        1
  1        1    ||   0       0           0        1

There are two security roles, staff and client; a person's role determines who they are, the roles are maintained in the database along with current state of the check boxes.

So I can simply store the users roll in the view class and enable and disable check boxes based on their role, but this doesn't seem proper. That is putting logic in UI to control which actions can be taken.

How do I get most of this control down into the model? I mean I need to control which check boxes are enabled and then check the results in the model when the form is posted, so it seems the best place for it to originate.

I am looking for a good approach to constructing this, something to follow as I build the application. If you know of some great references which explain these best practices that is really appreciated too.

+1  A: 

My approach tends to be to write the view so that the user can do anything and put all my validation in the model/service layer. Then when I've got that completely working, I'll add jQuery logic to make it more obvious to the user what they can and can't do and to avoid unnecessary postbacks wherever necessary.

I think it's a mistake to rely on the browser to block something the server will allow. The postback is too easy to fake and javascript can easily be turned off. However, where javascript can be used to improve the user experience or to save effort on the part of your server, you should do it.

And yes, that does sometimes mean repeated business logic but that's a sacrifice worth making. It's rarely actual repeated code. On the server side it's "if X is checked and Y is checked, return a message and don't store", on the client side it's "if X is checked, do not allow Y to be checked".

Make sense?

pdr
That is a lot of logic tied up in the UI, completely disconnected to the model logic. I completely agree that you want to guide the user as much as possible to making the correct selections. As you said, posts can be malformed in every which way, so all values need to be verified against your business logic.
Brettski
Well, yes. You can go further and set up your rules in the ViewModel, generating the javascript from those rules but you're into the realms of having to balance development time against maintenance time. That is going to depend on the likelihood of change, which is usually a guess. I would suggest applying the "take the bullet once" guideline, ie. take the easiest route and if you find it a problem later, rethink it.
pdr
+1  A: 

If you wanted to keep all the building of the UI within the model then you'd probably need to include a state with each checkbox. So your model would contain a checkbox object which in turn has the state attribute.

then in your view you could set the enabled flag using Model.CheckBoxName.state I guess.

this would then be true for every control that needs state information which would over complicate your model i think.

personally i'd keep a little of the smarts within the view as not every view that uses this model will require the state flag.

IMO a model should be as simple as can be. You could have a FormViewModel which describes the state of various controls which would remove the state from the model and i think that's a good idea.

@pdr makes a good point and rather than having a checkbox that's disabled you may consider having a label. but you still have the problem of faking a postback.

that can be easily captured because your formviewmodel can tell you whether to ignore submissions from disabled controls.

Anyway, if you want this in the model then i'd make a formviewmodel and have the state in there. I'd also be checking, on post, whether you can accept values from disbaled controls.

griegs
I guess part of what I am trying to avoid is having to hunt around for all the different places to apply a change. For instance, a new security role is created, Staff Mgr. This role is allowed to always update the client check box. So now I have to add to the UI the logic to allow the check box to be clicked, and add the check in the formviewmodel, or the model if logic is there, to allow this to happen.
Brettski
It sounds like what you are saying is that the business logic of who can click what, and verifying there are no false clicks (post injection) should be handled in the FormViewModel and not in model itself, say in a data repository?
Brettski
@Brettski, yeah kinda. Some validation can be in the model and some elsewhere. it's up to you to decide what will always need to be validated such as ages etc and what is required with privledges. i'm not sure, in a real world app, that validation belongs in a single place as pages have different needs.
griegs