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.
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.
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.
Take a look at the tutorials and sample projects on http://www.asp.net/mvc.
These all follow certain principles which would help you.
Related
I apologize in advance for the generic nature of my question, but I was unable to find any helpful advice from people trying to do the same thing as me on the web. Let me describe my scenario:
I am providing end users/designers of a website the ability to customize their views by storing the views (using Razor) in the database. I have all of this working, but my question is the following; From a security standpoint, how can I ensure and enforce that unwanted code doesn't get executed in the user-defined view? There are two basic approaches that I think will work conceptually, but am not sure which one is more possible or feasible.
Option 1: Create a validation method in the administration tool that allows the user to input the view code. This would need to either take a whitelist or blacklist approach to what is allowable or not.
Option 2: Prevent unwanted code from being able to execute when rendering of the view occurs.
As a quick example of something that would need to be blocked, we wouldn't want to allow access to read or write files, access any data access functions, or even access configuration settings, etc. in the web.config. There will likely be a decently-sized list of things that probably shouldn't be allowable, but I'll need to sit down and try to think of as many security-related concerns as possible.
My question then is, which method would be the best bet? Also, can any direction be provided on how to go about either? I thought I might be able to make trust-level based change which would be Option 2, but couldn't find any way to make that work in a per-view based manor (the administration code is allowed to execute whatever it wants). I'm thinking Option 1 will end up being the best bet and I'll have to check for the input of certain framework functions that shouldn't be allowed. Does anyone have any experience doing anything like what I'm trying to do? ANY feedback is much appreciated!
This would be extremely difficult.
You could run the the template through the Razor preprocessor, then use Roslyn (still in early beta) to parse the generated file and look through all method calls (or constructors) and return an error if it calls something you don't like.
I strongly recommend that you use a whitelist for that, since the .Net framework is big enough that you are bound to overlook something in a blacklist.
However, I would instead recommend that you not use Razor at all and instead use a templating engine that does not allow real C# code.
I have researched for some time the Orchard CMS and I'm pleased with some of his futures but also I have some issues that I don't know how to deal with them:
All the items (content type) are linear and they don't support a tree like data structure
(Ex: books > titles > web-links)
One of the big problem (depending how you see things) is that the model and the view for the items are coupled (content part > driver with display / editor views)
So for a new page the model, view and position are locked and you can have only one view of the model.
Use of advance language futures the are not suited for beginner developers and are not very clear (dynamic functions, clay objects - nice future, ...)
// Creating table VPlayerRecord
SchemaBuilder.CreateTable("VPlayerRecord", table => table
.ContentPartRecord()
.Column("Title", DbType.String)
.Column("VideoUrl", DbType.String)
.Column("WidthPx", DbType.Double)
.Column("HeightPx", DbType.Double)
);
This syntax is not very clear for beginner developers and is a bit over engineered. Also because the model is a dynamic object in the view we don't have any intellisense support.
To build a new page we have something like three degree of separation (3 projects)
Build a content part module
Build a content type
Build a theme module
How do you overcome these issues in your projects with Orchard CMS? and what other issues have you found and fixes :)
read this: http://orchardproject.net/docs/Creating-1-n-and-n-n-relations.ashx and this: http://orchardproject.net/docs/Creating-lists.ashx
How is this a problem and why do you see this as coupling? What alternative do you see?
Where do you see this as a problem and how has it blocked you?
edit on 2: it is not true that you can have only one view of the model. You can have any number of display types. For example, the summary view of items is handled this way. You also have display types for admin views, and you can add your own.
Not sure what you mean by "position is locked". If we mean the same thing by position, I'm puzzled by how you could have gotten such an idea. Relative positioning of parts and fields can be changed through placement.info.
edit on 3: even with this example, I'm not sure what would be difficult here. This is fairly expressive imo. Were you confused yourself or are you just assuming people would be?
You are claiming that this is over-engineered. How would you simplify it then? What feature do you think is not needed?
You don't get IntelliSense in views on model objects but the flexibility you gain by doing so justifies it by a very large margin. Ask anyone who's been making real use of it.
new 4th point: I can't see a reason why you would separate that into three modules or why you think you should. I've certainly never seen an example of that. I would also point out that creating a part and a type are often done by two different people (a type creator is often just a consumer of existing parts). But again you don't have to separate them into different modules.
A theme is clearly a different concern from the two others and makes sense to be a separate project but a theme can come with code and can actually in principle do everything a module is doing. So if you want to package a part, type and theme into a single package, you could do that. It wouldn't make a lot of sense but you could.
Finally, I don't see how any of those four points are related to page creation.
Orchard has to be taken as a challenge. As a beginner I have quickly built a few sites with ease. After that the learning curve became steeper. I've read many articles on the subject, numerous times.
I have used some CMS's before and had some knowledge what is the nature of managing content. Learning Orchard opened a whole new definition of content management. Now I can think of solving some everyday tasks and various business processes by implementing Orchard.
The whole thing is built in a very abstract layer, forcing you to think abstract too. If you follow this way, there are many blog posts, as well as official documentation to help you.
There are few basic building blocks and concepts that can be used like a bricks. Sounds like a phrase, I've heard it hunderts of times. I have also seen thousands of houses built from red square bricks, and they were all different, while the bricks were all equal. Such things can be accomplished with Orchard.
Read and understand the programming patterns. They are essential part of knowledge that will help you in solving Orchard based tasks. They will also help you change the way you are accomplishing your non Orchard related tasks.
I would say, there are two basic areas one need to understand. Storing and retreiving the piece of content is one, while presenting it to the crowd is the other. It might look difficult, it is difficult, but the goodies behind are delightfull. Not to mention great guys, some from evil empire, some not, that will certainly help you along the way. Not to forget, git's are your best friend. There are many wheels already invented. Caution, neither comes with free lunch.
P.S. I haven't write such a long post since usenet times. It might not be suitable for a site like this. It's kind a way to give a thanks to this French guy, and to all other Orchard evangelists from Poland, over Cyprus to the States. They saved my ass in many occasions.
For my new web app, I'm debating on using multiple views, or conditionals within views.
An example scenario would be showing different info to users who are authenticated vs non-authenticated. This could be handled a couple ways.
In the controller, check IsAuthenticated and return a view based on that
In the view, check IsAuthenticated and show blocks of info based on that
Pros of multiple views: Smaller, less complicated view - next to no logic in the view
Pros of single views: less view files to maintain
The obvious cons are the opposites of the pros: more files to maintain or more complicated view files.
Which do you prefer? Why? Any pros/cons I haven't outlined here?
Update: Assume each view uses a layout page and partial views to abstract the obviously repetitive code.
This sounds like a nice venue to discuss the merits of avoiding premature generalization. As the cousin to premature optimization, PG can be just as crippling. I say this because I often prematurely generalize and it tends to dissuade the ladies from flirting with me, laughing at my hilarious jokes, etc.
See: http://ryanfarley.com/blog/archive/2004/04/30/570.aspx
My general rule of thumb is this:
Repeat yourself twice.
When you're about to repeat yourself a third time, create an abstraction
I tend to follow this principle in my Views and my Partials:
I create my first View -- no
partials.
I create my second View -- no
partials.
I create my third View by
abstracting pieces of code from the
first and second View into reusable
partials.
I repeat until the Mountain Dew is all gone.
Though my answer to your question may seem overt, I think the point I'm trying to make is that, as developers, we tend to enjoy wasting a great deal of time contemplating the different ways that we can abstract away more and more layers from our individuated instantiations. Ironically, an abstraction is only valuable insofar as it reduces the necessity of repetition, and repetition is harmful only insofar as it reduces the likeliness that you'll accomplish anything, so a repetitive desire to over-abstract is just as detrimental as coding with a bunch of ON ERROR RESUME NEXT's.
I doubt that helped. But, alas.
I prefer a single view if it's simply an "if x display y" situation. Anything more than that and it can get out of control pretty easily. Reducing the duplicate html is worth the tradeoff of a small amount of simple logic, though.
I suspect the answers on this will be pretty much split down the middle because each side has its own merits.
i'd say it depends on how different the 2 scenarios are. if it's a major difference or a difference, do a separate view. if it's a difference that appears on multiple pages (like showing login controls vs. a signout button), make it into a separate partialview. for a couple of tiny differences, an if block is ok
I would say start with a single view...then depending on how complicated the difference between authenticated and unauthenticated views get, you can create multiple views.
I'm new at web development with .NET, and I'm currently studying a page where I have both separated codebehinds (in my case, a .CS file associated to the ASPX file), and codebehind that is inside the ASPX file inside tags like this:
<script runat="server">
//code
</script>
Q1:What is the main difference (besides logical matters like organization, readability and ETC), what could be done in one way that could not be done in another? What is each mode best suited for ?
Q2:If I'm going to develop a simple page with database connection, library imports, access to controls (ascx) and image access in other folders.. which method should I choose ?
Anything you can do in a code-behind, you can do in an inline script like what you posted. But you should use a code-behind most of the time anyway. Some things (like using directives) are just a little easier there, and it helps keep your code organized.
Q1: Nothing. Aside from what you and the others have mentioned (separation, readability), you can do everything "code behind" can do with "inline" (code within page itself) coding.
Inline coding doesn't necessarily mean its like "spaghetti code" where UI and code are mixed in (like old-school ASP). All your code can live outside of UI/HTML but still be inline. You can copy/paste all the code-behind code into your inline page and make a few adjustments (wiring, namespaces, import declarations, etc.) and that's that.
The other comments hit the nail: portability and quick fixes/modifications.
Depending on your use case, you may not want certain sections of code exposed (proprietary), but available for use. This is common for web dev professionals. Inline code allows your customers to quickly/easily customize functionality any way they want to, and can use some of your (proprietary) libraries (dlls) whenever they want to, without having to be code jocks (if they were, they wouldn't have hired you in the first place).
So in practical terms, it's like sending off an "html" file to clients containing instructions on how to change things around (without breaking things)...instead of sending off source code files along with html (aspx) pages and hoping your clients know what to do with them....
Q2: While either style (inline or code-behind) will work, its really a matter of looking at your application in "tiers". Usually, it will be: UI, business logic and data tiers. Thinking about things this way will save you a lot of time.
Practical examples:
If more than one page of your web app must expose/access data, then having a data tier is the best approach. Actually, even if you currently have a 1 page need, its likely never going to stay that way, so think of it as best practice.
If more than one page of your web app will collect input from users (i.e. contact us, registration/sign up, etc.) then you're likely going to need to validate input. So instead of doing this on a page by page basis, a common input validation library will save you time, and lessen the amount of code you need.
In the above examples, you've "separated" a lot of the processing into their own tiers. Your individual html/aspx pages can then use the "code libraries" (data and input validation) quickly with minimal code at the "page level". Then the decision to use either inline or code-behind styles at the "page level" wouldn't matter much - you've essentially "dumbed it down" to whatever your use case is at the time.
Hope this helps....
Keep it separated. Use the .aspx page for your layout, use the .aspx.cs page for any page specific code and for preference, pull your data access/business logic out into their own layer, makes for much simpler maintenance/re-use later on.
Slight caveat there - ASP.net MVC uses inline scripts in it's views, and I've really come round to that idea - it can keep the simple stuff simple, but the architecture used in MVC ensures that your business code remains separate from your presentation code.
I'm not saying you should ever be hacking live code... but one bit of flexibility from having the "code behind" as in-line script is that you could hack in changes without having to rebuild/publish the site.
Personally, I don't ever do this but I've heard instances where people have done it to get in an emergency fix.
There is no difference between the script tag and code behind. The code behind option actually came out of using the script tag or the <% %> from "Classic ASP". A lot of developers didn't like the fact that they server side code sat along side the UI code, because it made the file look messy, and it was a lot more difficult for the HTML people (web designers or whatever you would like to call them) to develop on the same page as the developers at the same time.
Most people like using the code behind option (It's actually considered the standard way of doing things), because it keeps the UI and the Code separate. It's what I prefer, but you really can use either.
You can use all the same stuff
Always try to keep the code separated unless you have a compelling reason not to
Funnily enough, I used the <script runat="server"> in the code infront only today! I did this because you do not need to Build the whole web application to deploy a fix that needs code behind. Yes- it was a bug fix ;)
I'm currently building a single page AJAX application. It's a large "sign-up form" that's been built as a multi-step wizard with multiple branches and different verbiage based on what choices the user makes. At the end of the form is an editable review page. Once the user submits the form, it sends a rather large email to us, and a small email to them. It's sort of like a very boring choose your own adventure book.
Feature creep has pushed the size of this app beyond the abilities of the current architecture, and it's too slow to work in any slower computers (not good for a web app), especially those using Internet Explorer. It currently has 64 individual steps, 5400 DOM elements and the .aspx file alone weighs in at 300kb (4206 LOC). Loading the app takes anywhere from 1.5 seconds on a fast machine running FireFox 3, to 20 seconds on a slower machine running IE7. Moving between steps takes about the same amount of time.
So let's recap the features:
Multi-Step, multi-path wizard style
form (64 steps)
Current step is shown in a fashion similar to this: http://codylindley.com/CSS/325/css-step-menu
Multiple validated fields
Changing verbiage based on user
choices
Final, editable review page
I'm using jQuery 1.3.2 and the following plugins:
jQuery Form Wizard Plugin
jQuery clueTip plugin
jQuery sexycombo
jQuery meioMask plugin
As well as some custom script for loading the verbiage from an XML file, running the review page and some aesthetic accoutrements.
I don't have this posted anywhere public, but I'm mostly looking for some tips on how to approach this sort of project and make it light weight and extensible. If anyone has any ideas as far as tools, tutorials or technologies, that's what I'm looking for. I'm a pretty novice programmer (I'm mostly a CSS/xHTML/Design guy), so speak gently. I just need a good plan of attack to make this app faster. Any ideas?
One way would be to break apart the steps into multiple pages / requests. To do this you would have to store the state of the previous pages somewhere. You could use a database to do this or some other method.
Another way would be to dynamically load the parts you need via AJAX. This won't help with the 54000 DOM elements though, but it would help with the initial page load.
Based on the question comments a quick way to "solve" this problem is to make a C# class that mirrors all the fields in your question. Something like this:
public class MySurvey
{
public string FirsName { get; set; }
public string LastName { get; set; }
// and so on...
}
Then you would store this in the session (too keep it easy... I know it's not the "best" way) like this
public MySurvey Survey
{
get
{
var survey = Session["MySurvey"] as MySurvey;
if (survey == null)
{
survey = new MySurvey();
Session["MySurvey"] = survey;
}
return survey;
}
}
This way you'll always have a non-null Survey object you can work with.
The next step would be to break that big form into smaller pages, let's say: step1.aspx, step2.aspx, step3.aspx etc. All these pages would inherit from a common base page that would include the property above. After this all you'd need to do is send the request from step1.aspx back and save it to Survey, similar to what you're doing now but for each small piece. When done redirect (Response.Redirect("~/stepX.aspx")) to the next page. The info from the previous page would be saved in the session object. If they close the browser page they won't be able to get back though.
Rather than saving it to the session you could save it in a database or in a cookie, but you're limited to 4K for cookies so it may not fit.
I agree with PBZ, saving the individual steps would be ideal. You can, however, do this with AJAX. If you did, though, it'd require some stuff that sounds like it might be outside of your skillset of mostly front-end development, you'd need to probably create a new database row and tie it to the user's session ID, and every time they click to the next step have it update that row. Possibly even tie it to their IP address so if the whole thing blows up they can come back and hit "remember me?" for your application to retrieve it.
As far as optimizing the existing structure, jQuery is fairly heavy when it comes to optimization, and adding a lot of jQuery modules doesn't help that. I'm not saying it's bad, because it saves you a lot of time, but there are some instances where you are using a module for one of its many functionalities, and you can replace that entire module with a few lines of jQuery enabled javascript.
As far as minimizing the individual DOM elements, the step above I mentioned could help slim that down, because you're probably loading a lot of extensible functions for those modules that you may or may not need.
On the back end, I'd have to see the source to see how to tell you to optimize it, but it sounds like there's a lot of redundancy in individual steps, some of that can probably be trimmed down into functions that include a little recursion, or at the least delegate some of the tasks to one another.
I wish I could help more but without digging through your source I can only suggest basic strategies. Best of luck, though!
Agree, break up the steps. 5400 elements is too many.
There are a few options if you need to keep it on one page.
AJAX requests to get back either raw HTML, or an array of objects to parse into HTML or DOM
Frames or Iframes
JavaScript to set innerHTML or manipulate the DOM based on the current step. Note with this option IE7 and especially IE6 will have memory leaks. Google IE6 JavaScript memory leaks for more info.
Use document.write to include only the .js file(s) needed for the current step.
HTH.
Sounds like mostly a JQuery optimization problem.
First suggestion would be switch as many selects into ID selectors as you can. I've had speedups of over 200-300x by being able to move to id attribute selection only.
Second suggestion is more of a plan of attack. Since IE is your main problem area, I suggest using the IE8 debugger. You just need to hit f12 in IE8... Tabs 3 and 4 are script and profiler respectively.
Once you've done as much of #1 as you think you can, to get a starting point, just go to profiler, hit start profiling, do some slow action on the webpage, and then stop profiling. You will see your longest method calls, and just work your way through it.
For finer testing/dev, go to the script tab. Breakpoints locals etc are there for analysis. You can dev/test changes via the immediate window... i.e. put a break point where you want to change a function, trigger the function, execute your javascript instead of the defined javascript in the immediate window.
When you think you have something figured out, profile your changes to make sure they are really improvements. Just start the profiler, run the old code, stop it and note your benchmark. Then re-start the profiler and use the immediate window to execute your altered function.
That's about it. If that flow can't take you far enough, as mentioned above, JQuery itself (and hence its plugins) are not terribly performant, and replacing with standard javascript will speed everything up. If your plugins benchmark slow, look at replacing them with other plugins.