views:

146

answers:

3

Hi

I am making a web application in asp.net mvc C# with jquery that will have different pricing plans.

Of course the more you pay the more features you get.

So I was planning to use roles. So if someone buys plan 1 then they get a role of plan 1. Then on the page use an if statement to check if they are in certain roles. If they are allowed to use the feature generate it. If not do nothing.

It could be very well be that the entire page might be shared among all the roles except maybe one feature on that page.

Now someone was telling me that I should not do the way I am thinking of it since if I add more features then my page will get more cluttered with if statements and it will be hard to maintain.

They said I should treat each plan as a separate application. So if I have 2 plans have 2 different links going to different files.

I agree with the person that it probably will be better in the long run since I won't have to keep tacking on if statements but the thing that gets me is say in this scenario.

In the future versions of my site I will have SMS and Email alerts.

Right now I have a Html table with a set of tasks the user has to do. In future versions of the site I will give the option to get alerted by email OR SMS. If they choose say to be alerted by email in a table column an envelope will appear.

Now this might only be for people who are on Plan 2 and not Plan 1. So the solution of the person was just copy and paste all the code for the table code stick in a file called Plan2.aspx. Then add the new row for the icons to the newly pasted code for Plan 2.

Now I would have a Plan1 file that has everything the same except for this extra row that is in the Plan2 file.

So I am not too crazy about that idea because of duplicate code if something is wrong with the table I now have to change it into 2 locations not one. If I add a 3rd plan now I need to keep track of 3 sets of the same code with some varying differences.

My original way would have been that row in the table that is only for plan2 would be surrounded by an if statement checking their role.

Like in some cases I probably will be able to put all the common code into one partial control and all the different code in another partial control but its situations like this that I am not sure about.

There will be many more of these situations this just one example.

So what is the best way to make your code maintainable but also have minimal amounts of duplicate code.

Sorry for the post its kinda hard to describe what I am trying to achieve and situations that are that are could be possible areas of trouble.


Edit

So I am still kinda confused by the examples people have given and would love to see little full examples of them and not just stubs.

I was also thinking but I am not sure if this would be good practice or what and might look pretty strange and some parts.

Is to have everything in common in a partial view even if it is just like one line. Then have 2 separate links and just put the partial views together depending on their role.

I am thinking about the 2 seperate links because of the jquery stuff. Like for instance if I had this

<textbox code>
<textbox code> // this textbox code is only for plan 2 ppl. This textbox needs to go here
<textbox code>

Each of these textboxes tags would be in its own partial view(so 3 in this case)

so I would have 2 aspx pages.

1st

<render partialView 1>
<render partialView 2>
<render partialView 3>

2nd

<render partialView 1>
<render partialView 3>

Then in each of these 2 aspx pages would have different javascript files linked up.

The thing what I was thinking of if I just have like one javascript file with my jquery someone can just go and add the missing html ones and have access to all those features.

So I am not sure how I would write it if I am using the "if statement" way.

But at the same time have everything in partialView will look very funny. Like if I am making a table or something.

One partial view would have the start tag and some rows then X partial views down the road would have the closing tag.

Will look very weird and hard to see the whole picture since you will have to open up X amount of files to see the whole picture.

So there is got to be a better way.

A: 

Take a look at the tutorials and sample projects on http://www.asp.net/mvc.

These all follow certain principles which would help you.

Ropstah
+2  A: 

How well abstracted are the components?

My naive approach would be to create a separate layer that dishes the components out to the UI. Something like a repository pattern, with a method like this:

public IEnumerable<PlanRestrictedFeature> GetFeaturesForPlan(Role r)
{
     //return all features that the user has access to based on role
     //this forces all this logic to exist in one place for maintainability
}

Of course, the method could also take in a string, enum, or Plan object, if you have one. Internally, this may use some type of map to make things simpler.

Then, the View can simply call the Render method of each component. Make sure the repository passes them back in the correct order for rendering, and rely on CSS for placement.

JoshJordan
Sorry what do you mean by "How well abstracted are the components"?Also I not following too much could you please whip up a very simple example nothing fancy just enough to show me what you are trying to do?
chobo2
A: 

Whilst it's not the best practice to have a view littered with if statements (see Rob Conery's blog post on the matter), some rudimentary logic, is in my opinion, acceptable. If you do this though, you should try to use partials to keep the view as uncluttered as possible. This, as you pointed out is what you think is the best solution.

Your view logic really should be as simple as possible though and your models would benefit from inheriting your price plan information to save duplicating the code itself.

Removed the other code, as you pointed out that you would just use the User class.

Regarding the textbox, this could be trickier. One thought is that you could have your scripts folders which contain global JS, and then subfolders that have JS specifically for other roles (Role 2 and 3 for example). These could be protected by a custom route constraint which prevents users from accessing the file/folder without the relevant level of authentication. You should also use a web.config to provide a similar level of protection. That, or just use the web.config file.

Dan Atkinson
Hi well first I still looking how to do the best practices. Will I do the best practice every single time? Probably not but still good to know.I think trying to a mixuture of what the person told me and what I want to do probably will be a good way.Like for the case where I just need one more <tr> tag it seems stupid to duplicate the code twice. So I am not sure what your dong though with the Model. Why do you need to use a model? Can't you just go "User.IsInRole("role")" instead of making a model?One other thing I am not too sure about it is say one pricing plan has an extra textbox
chobo2
this textbox is hooked up to jquery. How would I add the jquery only when the user has access to that role. Like if I just leave all the jquery stuff a person looking at the code might see that they just need to make a textbox and it will get hooked up to the jquery. so I can't leave it lying around.
chobo2
Regarding, the User.IsInRole(), yes, you're right, you can use that. I juse tend to use a lot of business logic specific properties that aren't part of User. I'll update the answer to discuss the textbox...
Dan Atkinson
HmmBut I usually paste the javascript links all in the header. Will they get blocked if the user does not have permissions or what happens?Also I was thinking how about using a foreach loop and passing in all the names through the Model State. How the foreach loop go around that many times to generate all the textboxes.the only problem I see with that I might need to break up it to many for each loops.It would be nice if you could throw and html helper in the for-each loop and if a "null" value was sent it it just would not render the control instead of throwing an error.
chobo2