I am designing a data driven web site that has a page that shows a list people with associated data - contact information, hobbies etc. Each list is fairly static- it changes rarely. Presently, when a list is loaded, the data is fetched from rows containing people data from an azure table. This process is making my page loads unacceptably slow. My question is, can I pre-assemble the entire people list page html, with the associated data for each list, and save if to a blob storage? This way, if a user wants to see, say, "people list A", the pre-assembled list is received from an azure blog container and served directly to the client? I did look at azure redis, but it looks like it would be more expensive and perhaps more complicated to implement.
You have several (almost) build-in options. With ASP.net MVC you can use output caching which works out of the box, but it's only really usable if you want to return the same data to many people. Although you can use the VaryByParam property to cache several different versions of the same page.
Another option, you already mentioned, is caching the data externally. You can save the list of people in Redis, or just in a MemoryCache which is available since .NET Framework 4.5.
Rendering the whole page, capturing the output, saving it to blob storage, retrieve it when necessary, send it to the user and manage the caching sounds way to complicated to me for solving this common problem. I prefer the first two solutions, which are meant for scenario's like this and are used to great effect by millions of sites.
Related
So I've been looking into effective ways to take the load off of my database in my ASP.NET application, and I've run into the System.Web.Mvc.OutputcCacheAttribute. I've used caching based on System.Web.HttpRuntime.Cache before, it seems to be pretty much functionally equivalent.
I've done a lot of research on it, and everything I've seen portrays it as some sort of silver bullet for caching requests as long as you configure it effectively. I find this hard to believe. I understand that all it really takes (to a degree) for some effective caching is storing the output data based on certain conditions, but it still just seems too easy to just tack on an attribute and have your application magically perform better.
Has anyone had any experience with the benefits/drawbacks of using Output Caching in ASP.NET? If so, what are the pain points of using this approach to caching?
Caching can do wonders, by trading latency for memory. The devil's in the "configuring it effectively."
The important thing is to nail down for yourself what is acceptable behavior in the application, e.g., is it ok if the "top 3 posts" on the front page is up to 1 minute old? Is it ok if the "current users online" list is up to 30 seconds old? Is it ok if the main page takes 0.75 seconds to load, or does it need to be faster? Your answers to these questions will determine what should or should not be cached. Profile your application so you understand where the real performance bottlenecks are, and why they exist, so you know where to focus your optimization/caching efforts
There are many forms of caching available in a .Net application. OutputCache is just one form:
Application-Level Caching (shared by everything in the application - Application[Key])
Object Caching (automatically managed with cache invalidation callbacks - Cache[Key])
Output Caching (caching the generated output of aspx pages/parts - OutputCache property)
Per-Request Caching (caching calculated data during a single request - Context[key])
Session Caching (caching data specific to a user's session - Session[key])
They all have their pros and cons, and a well-designed application will probably make use of most or all of these forms of caching. If you want some points to consider with OutputCache, here are a few:
Try to cache parts of a page rather than a full page, because they are more likely to be re-usable. Building your pages out of components like a UserControl can help here.
Be careful with using a set of parameters that vary greatly, such as a QueryString parameter that is different per item id, because you will end up generating a lot of cached copies that are used infrequently, consuming lots of memory with very little benefit.
Note that OutputCache is merely saving the generated output of the ASPX markup. So it will not work as well as other caching types in a dynamic page that changes form based on user input.
From my experience, there is one very obvious and very often forgotten thing about this attribute.
It is the fact that method, which output is cached, won't be even executed after being cached. So, if the code behind the action has some side effects, they won't take place (e.g. logging to the database DB the fact, that use visited the page).
I have seen at least few very nasty bugs, because of that.
Short advice: use it sparsely and be 101% sure that every dev in the team knows very well how it works.
The Problem
In the stack that we re-use between projects, we are putting a little bit too much data in the session for passing data between pages. This was good in theory because it prevents tampering, replay attacks, and so on, but it creates as many problems as it solves.
Session loss itself is an issue, although it's mostly handled by implementing Session State Server (or by using SQL Server). More importantly, it's tricky to make the back button work correctly, and it's also extra work to create a situation where a user can, say, open the same screen in three tabs to work on different records.
And that's just the tip of the iceberg.
There are workarounds for most of these issues, but as I grind away, all this friction gives me the feeling that passing data between pages using session is the wrong direction.
What I really want to do here is come up with a best practice that my shop can use all the time for passing data between pages, and then, for new apps, replace key parts of our stack that currently rely on Session.
It would also be nice if the final solution did not result in mountains of boilerplate plumbing code.
Proposed Solutions
Session
As mentioned above, leaning heavily on Session seems like a good idea, but it breaks the back button and causes some other problems.
There may be ways to get around all the problems, but it seems like a lot of extra work.
One thing that's very nice about using session is the fact that tampering is just not an issue. Compared to passing everything via the unencrypted QueryString, you end up writing much less guard code.
Cross-Page Posting
In truth I've barely considered this option. I have a problem with how tightly coupled it makes the pages -- if I start doing PreviousPage.FindControl("SomeTextBox"), that seems like a maintenance problem if I ever want to get to this page from another page that maybe does not have a control called SomeTextBox.
It seems limited in other ways as well. Maybe I want to get to the page via a link, for instance.
QueryString
I'm currently leaning towards this strategy, like in the olden days. But I probably want my QueryString to be encrypted to make it harder to tamper with, and I would like to handle the problem of replay attacks as well.
On 4 guys from Rolla, there's an article about this.
However, it should be possible to create an HttpModule that takes care of all this and removes all the encryption sausage-making from the page. Sure enough, Mads Kristensen has an article where he released one. However, the comments make it sound like it has problems with extremely common scenarios.
Other Options
Of course this is not an exaustive look at the options, but rather the main options I'm considering. This link contains a more complete list. The ones I didn't mention such as Cookies and the Cache not appropriate for the purpose of passing data between pages.
In Closing...
So, how are you handling the problem of passing data between pages? What hidden gotchas did you have to work around, and are there any pre-existing tools around this that solve them all flawlessly? Do you feel like you've got a solution that you're completely happy with?
Thanks in advance!
Update: Just in case I'm not being clear enough, by 'passing data between pages' I'm talking about, for instance, passing a CustomerID key from a CustomerSearch.aspx page to Customers.aspx, where the Customer will be opened and editing can occur.
First, the problems with which you are dealing relate to handling state in a state-less environment. The struggles you are having are not new and it is probably one of the things that makes web development harder than windows development or the development of an executable.
With respect to web development, you have five choices, as far as I'm aware, for handling user-specific state which can all be used in combination with each other. You will find that no one solution works for everything. Instead, you need to determine when to use each solution:
Query string - Query strings are good for passing pointers to data (e.g. primary key values) or state values. Query strings by themselves should not be assumed to be secure even if encrypted because of replay. In addition, some browsers have a limit on the length of the url. However, query strings have some advantages such as that they can be bookmarked and emailed to people and are inherently stateless if not used with anything else.
Cookies - Cookies are good for storing very tiny amounts of information for a particular user. The problem is that cookies also have a size limitation after which it will simply truncate the data so you have to be careful with putting custom data in a cookie. In addition, users can kill cookies or stop their use (although that would prevent use of standard Session as well). Similar to query strings, cookies are better, IMO, for pointers to data than for the data itself unless the data is tiny.
Form data - Form data can take quite a bit of information however at the cost of post times and in some cases reload times. ASP.NET's ViewState uses hidden form variables to maintain information. Passing data between pages using something like ViewState has the advantage of working nicer with the back button but can easily create ginormous pages which slow down the experience for the user. In general, ASP.NET model does not work on cross page posting (although it is possible) but instead works on posts back to the same page and from there navigating to the next page.
Session - Session is good for information that relates to a process with which the user is progressing or for general settings. You can store quite a bit of information into session at the cost of server memory or load times from the databases. Conceptually, Session works by loading the entire wad of data for the user all at once either from memory or from a state server. That means that if you have a very large set of data you probably do not want to put it into session. Session can create some back button problems which must be weighed against what the user is actually trying to accomplish. In general you will find that the back button can be the bane of the web developer.
Database - The last solution (which again can be used in combination with others) is that you store the information in the database in its appropriate schema with a column that indicates the state of the item. For example, if you were handling the creation of an order, you could store the order in the Order table with a "state" column that determines whether it was a real order or not. You would store the order identifier in the query string or session. The web site would continue to write data into the table to update the various parts and child items until eventually the user is able to declare that they are done and the order's state is marked as being a real order. This can complicate reports and queries in that they all need to differentiate "real" items from ones that are in process.
One of the items mentioned in your later link was Application Cache. I wouldn't consider this to be user-specific since it is application wide. (It can obviously be shoe-horned into being user-specific but I wouldn't recommend that either). I've never played with storing data in the HttpContext outside of passing it to a handler or module but I'd be skeptical that it was any different than the above mentioned solutions.
In general, there is no one solution to rule them all. The best approach is to assume on each page that the user could have navigated to that page from anywhere (as opposed to assuming they got there by using a link on another page). If you do that, back button issues become easier to handle (although still a pain). In my development, I use the first four extensively and on occasion resort to the last solution when the need calls for it.
Alright, so I want to preface my answer with this; Thomas clearly has the most accurate and comprehensive answer so far for people starting fresh. This answer isn't in the same vein at all. My answer is coming from a "business developer's" standpoint. As we all know too well; sometimes it's just not feasible to spend money re-writing something that already exists and "works"... at least not all in one shot. Sometimes it's best to implement a solution which will let you migrate to a better alternative over time.
The only thing I'd say Thomas is missing is; client-side javascript state. Where I work we've found customers are coming to expect "Web 2.0"-type applications more and more. We've also found these sorts of applications typically result in much higher user satisfaction. With a little practice, and the help of some really great javascript libraries like jQuery (we've even started using GWT and found it to be AWESOME) communicating with JSON-based REST services implemented in WCF can be trivial. This approach also provides a very nice way to start moving towards a SOA-based architecture, and clean separation of UI and business logic.
But I digress.
It sounds to me as though you already have an application, and you've already stretched the limits of ASP.NET's built-in session state management. So... here's my suggestion (assuming you've already tried ASP.NET's out-of-process session management, which scales signifigantly better than the in-process/on-box session management, and it sounds like you have because you mentioned it); NCache.
NCache provides you with a "drop-in" replacement for ASP.NET's session management options. It's super easy to implement, and could "band-aid" your application more than well enough to get you through - without any significant investment in refactoring your existing codebase immediately.
You can use the extra time and money to start reducing your technical debt by focusing new development on things with immediate business-value - using a new approach (such as any of the alternatives offered in the other answers, or mine).
Just my thoughts.
Several months later, I thought I would update this question with the technique I ended up going with, since it has worked out so well.
After playing with more involved session state handling (which resulted in a lot of broken back buttons and so on) I ended up rolling my own code to handle encrypted QueryStrings. It's been a huge win -- all of my problem scenarios (back button, multiple tabs open at the same time, lost session state, etc) are solved and the complexity is minimal since the usage is very familiar.
This is still not a magic bullet for everything but I think it's good for about 90% of the scenarios you run into.
Details
I built a class called CorePage that inherits from Page. It has methods called SecureRequest and SecureRedirect.
So you might call:
SecureRedirect(String.Format("Orders.aspx?ClientID={0}&OrderID={1}, ClientID, OrderID)
CorePage parses out the QueryString and encrypts it into a QueryString variable called CoreSecure. So the actual request looks like this:
Orders.aspx?CoreSecure=1IHXaPzUCYrdmWPkkkuThEes%2fIs4l6grKaznFGAeDDI%3d
If available, the currently logged in UserID is added to the encryption key, so replay attacks are not as much of a problem.
From there, you can call:
X = SecureRequest("ClientID")
Conclusion
Everything works seamlessly, using familiar syntax.
Over the last several months I've also adapted this code to work with edge cases, such as hyperlinks that trigger a download - sometimes you need to generate a hyperlink on the client that has a secure QueryString. That works really well.
Let me know if you would like to see this code and I will put it up somewhere.
One last thought: it's weird to accept my own answer over some of the very thoughtful posts other people put on here, but this really does seem to be the ultimate answer to my problem. Thanks to everyone who helped get me there.
After going through all the above scenarios and answers and this link Data pasing methods My final advice would be :
COOKIES for:
ENCRYPT[userId's]
ENCRYPT[productId]
ENCRYPT[xyzIds..]
ENCRYPT[etc..]
DATABASE for:
datasets BY COOKIE ID
datatables BY COOKIE ID
all other large chunks BY COOKIE ID
My advise also depends on the below statistics and this link details Data pasing methods :
I would never do this. I have never had any issues storing all session data in the database, loading it based on the users cookie. It's a session as far as anything is concerned, but I maintain control over it. Don't give up control of your session data to your web server...
With a little work, you can support sub sessions, and allow multi-tasking in different tabs/windows.
As a starting point, I find using the critical data elements, such as a Customer ID, best put into the query string for processing. You can easily track/filter bad data coming off of these elements, and it also allows for some integration with e-mail or other related sites/applications.
In a previous application, the only way to view an employee or a request record involving them was to log into the application, do a search for the employee or do a search for recent records to find the record in question. This became problematic and a big time sink when somebody from a related department needed to do a simple view on records for auditing purposes.
In the rewrite, I made both the employee Id, and request Ids available through a basic URL of "ViewEmployee.aspx?Id=XXX" and "ViewRequest.aspx?Id=XXX". The application was setup to A) filter out bad Ids and B) authenticate and authorize the user before allowing them to these pages. What this allowed the primarily application users to do was to send simple e-mails to the auditors with a URL in the e-mail. When they were in a big hurry, they were in their bulk processing time, they were able to simply click down a list of URLs and do the appropriate processing.
Other session related data, such as modification dates and maintaining the "state" of the user's interaction with the application gets a little more complex, but hopefully this provides a starting poing for you.
I have a question about storing site configuration data.
We have a platform for web applications. The idea is that different clients can have their data hosted and displayed on their own site which sits on top of this platform. Each site has a configuration which determines which panels relevant to the client appear on which pages.
The system was originally designed to keep all the configuration data for each site in a database. When the site is loaded all the configuration data is loaded into a SiteConfiguration object, and the clients panels are generated based on the content of this object. This works, but I find it very difficult to work with to apply change requests or add new sites because there is so much data to sift through and it's difficult maintain a mental model of the site and its configuration.
Recently I've been tasked with developing a subset of some of the sites to be generated as PDF documents for printing. I decided to take a different approach to how I would define the configuration in that instead of storing configuration data in the database, I wrote XML files to contain the data. I find it much easier to work with because instead of reading meaningless rows of data which are related to other meaningless rows of data, I have meaningful documents with semantic, readable information with the relationships defined by visually understandable element nesting.
So now with these 2 approaches to storing site configuration data, I'd like to get the opinions of people more experienced in dealing with this issue on dealing with these two approaches. What is the best way of storing site configuration data? Is there a better way than the two ways I outlined here?
note: StackOverflow is telling me the question appears to be subjective and is likely to be closed. I'm not trying to be subjective. I'd like to know how best to approach this issue next time and if people with industry experience on this could provide some input.
if the information is needed for per client specific configuration it is probably best done in a database with an admin tool written for it so that non technical people can also manage it. Also it's easier that way when you need versioning/history on it. XML isn't always the best on that part. Also XML is harder to maintain in the end (for non technical people).
Do you read out the XML every time from disk (performance hit) or do you keep it cached in memory? Either solution you choose, caching makes a big difference in the end for performance.
Grz, Kris.
You're using ASP.NET so what's wrong with web.config for your basic settings (if it's per project deploy), then as you've said, custom XML or database configuration settings for anything more complicated (or if you have multiple users/clients with the same project deploy)?
I'd only use custom XML documents for something like a "site layout document" where things won't change that often and you're going to have lots of semi-meaningless data (e.g. 23553123). And layout should be handled by css as much as possible anyway.
For our team XML is a good choice (app.config or web.config or custom configuration file, it depends), but sometimes it is better to design configuration API to make configurations in code. For example modern IoC containers has in-code configuration APIs with fluent interfaces. This approach can give benefits if you need to configure many similar to each other entities or want to achive good human readability. But this doesn't works if non-programmers need to make configurations.
I'm creating an ASP.Net website that displays large amounts of data. The data is served to me through a data access layer. From the data I'm getting I'm building up large data tables and then displaying these using either gridview's or dynamically created web controls.
The problem I'm finding is that the website is slow when a lot of data is passed to it. I've read that data readers are the way to go but I can't use a datareader directly from the SQL table due to needing to use the data access layer.
I also don't have the option of partially filling the datatable as I need to apply a lot of sorting methods to the data to display what I need.
Any suggestions of ways to speed up data tables? or perhaps use something else that's more efficient?
Since you are “.. building up large data tables and then displaying these using either gridview's or dynamically created web controls”, the network can be a bottleneck. See the answers to the similar SO question that may be helpful.
Are you absolutely certain that the bottleneck is in the Web Application?
The first thing I would do would be to guess what the longest SQL query you execute on a slow page would be, then see how it runs in the query browser.
If it's slow, work on optimizing that.
Pulling 'large' amounts of data into a web application and doing sorting / filtering there is always going to be slow, depending on your definition of 'large'. If you can apply any sorting / filtering on the database server before you pull the data to your web application that should speed things up. You say you don't have the option to do this but sorting is something that database servers are made for, are you sure you can't make this work?
You can use distributed cache, to cache your data. Memcache (http://www.danga.com/memcached/) or Velocity Microsoft Distributed Cache (http://www.microsoft.com/downloads/details.aspx?FamilyId=B24C3708-EEFF-4055-A867-19B5851E7CD2&displaylang=en).
The first thing you will want to do is to pinpoint exactly what part of the process that is being slow. It might not be where you think it is. Do code profiling or timing of different parts to determine exactly how much time each piece of code consume during a request. In our case we found that the data layer (executing readers, populating object models) were really fast (with a couple of exceptions that were taken care of by indexes in the database), while we had some javascript on the client that was really slow.
So, start with measuring, then decide where to optimize.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
Visual studio is pretty good but doesn't create stored procedures automatically. Iron Speed designer does supposedly. But is it any good?
I have used Ironspeed extensively for the past two years for most of our ASP.NET forms over data projects.
It works. Does several things well: stored procs, fast layout of table browse and CRUD screens, fast layout of single record CRUD screens. It manages the round-trip (or half-round trip) process decently, detecting changes in your back end db schema and updating its data access layer, then making the changed columns available for you to alter your UI (in record or table control panels). ISD (as they call it) does an excellent job in making security management for your app pretty painless, even down to the control level (if you use ISD's subclassed versions of asp.net controls). Final plus, not a small one, is the CSS-based theme control (easy to change to a variety of themes, easy to customize a particular theme, and not even too bad to build your own theme variant by forking an existing one you like). Depending upon whether you let ISD create your stored procs in the code base or the database, changing DB's at run time can be a piece of cake.
Fairly active forum with a core group of helpful contributors. You can probably avoid the paid tech support through the forum.
Okay, the down sides. Creates fairly large code conglomerations, being a three tiered architecture. As Galwegian says, like any framework, you've got the velvet handcuffs (get your mind out of the gutter if you are thinking about anything other than code limitations and conventions!). The velvet handcuffs are the page and control model, the data layer, lack of a business object/class capability per se, the postback model, and the temptation to make your user GUI look like THEIR user GUI that comes out of the box because it is so darned easy and convenient.
ISD builds a basic page by combining an HTML template (in to which you place ISD specific code generation tags and any other tags, etc., you which using the ISD GUI or by hand). The page model relies upon a code behind page created from a piece of code template. The base classes are almost completely overridable, so that you can override all of the default functions, regenerate the application and not lose your overrides. The database controls live in the page container, but have their own class definitions (i.e., their code-behind) in specific /app_code files. Again, each control type has its own base class with pretty completely overridable methods. A single record control (showing a single db record) is pretty simple. A table, showing several records, has a table class and a table row class. The ISD website (www.ironspeed.com/support) has good documentation of the ISD model as a whole.
So, where are the problems in this model?
1. Easy and tempting to live with their out of the box GUI. Point ISD at your database, pick the tables you want to have it turn in to pages, tell it the kinds of pages, give it a thematic style and five minutes later you're viewing the application. Cool. But, it is very easy to forget that their user GUI is probably not what your user wants to see. So, be prepared to think for yourself and tinker with the GUI thus created. Not hard to do, and you can use VS 2005 to help you.
Business objects. You could put together your own business objects, but it would be difficult and you would get no help from ISD. ISD does a LOT of building of simple validation and checking (appropriate look up values, ranges, lengths, etc.) ISD lets you build custom queries, but these are read-only. It is smart enough (and you can override the write from a page in any case) to let you take a one to many view and write it back to the database (you'd probably override the default base method, but it isn't that hard to do). However, when you get in to serious dependency checking, ISD is still really about tables and not business objects. So, you're going to write some code.
If you are smart, you'll write it once store it in app_code somewhere and use it by calling it from an overridden method in your table or record controls. If you are like most of us, you'll first spaghetti it in to one of the code-behind classes above, and then forget you did so, or have a copy in each of the 10 pages that manipulates customer data. In my world, that has usually meant 5 identical functions and 5 that are all different (even though they are all supposed to be the same). ISD makes it tempting to order marinara, because the model lends itself to spaghetti code. Of course, you can completely prevent this, but you gotta learn the ISD model to determine the best way to do it on your project.
Page state and postbacks. Although ISD is quite open about this problem and tells users not to just take the defaults of returning the whole asp.net page state in the postback stream (cache on the server instead), the default is to return the whole page. Can make for some BIG pages. Which makes users think S L O W. As I said, you can manipulate this. But, what newbie is going to get this when it is SO tempting to just point, click, and boom - instant application. Your manager is now off your back because her product inventory table is "on the web" with a cool search and edit GUI (of 400kb state pages if you've gone a bit nuts and have just taken the default behaviors of ISD). Great in-house, but the customers in the real world....
Again, knowledge is the key. You can fix this, but you need to know you SHOULD.
Database read/write postbacks. No big problem here, but you also need to know that the model is to fetch only the data used at the moment. If your table shows 1000 records in 50 record increments, when you go from records 1 to 50 to 51 through 100, you will postback and hit the database again. This keeps data current, but increases server traffic.
Overall: Try the demo version. Point it at something simple that you really want to turn in to an asp.net application. Build maybe three tables. Then dissect it using the above as a guide. See what YOU think and post back to this question.
I have used it for convenience for a very small project. It did what I wanted and saved me a couple of days work.
The main problem I found was when it came to customising or extending the generated project. You have to spend quite a bit of time trying to understand Ironspeed's way of doing things which, I'll admit, is not my way.
I'd use it again for a small project if I knew in advance I wouldn't have to customise it much after.
If stored procedure generation is all you are after, CodeSmith is a decent option at a fraction of the cost of IronSpeed. There are several sproc templates available, and you can create your own or tweak an existing if that is what you need. You can also gen .Net code to your hearts content with CodeSmith. Tons of business class templates already exist for this.
IronSpeed's value is not in the sproc generation, but in the RAD features. I agree with #Galwegian... IronSpeed is OK for mock ups or very simple apps, not so good at all if you need to do any customization.
You may want to check out Evolutility CRUD framework. It provides some of the same features (limited to CRUD) and is open source.
IronSpeed has been great (out-of-the-box) at helping me develop data-driven corporate Intranet applications. While the code model takes a little getting used to, it is effective at maintaining a nice three-tier app. While the page templates can appear garish compared to 2010's web-design, it gets the job done, when you need function over form.
Iron Speed Designer is great for simple CRUD type web applications. You can find some useful information on our web site http://www.dotnetarchitect.co.uk/