Fetch userdata on each request - asp.net

My problem is quite simple - I think. I'm doing an ASP.NET MVC project. It's a project that requires the user to be logged in at all time. I probably need the current user's information in the MasterPage, like so; "Howdy, Mark - you're logged in!".
But what if I need the same information in the view? Or some validation in my servicelayer?
So how to make sure this information is available when I need it, and where I need it?

How much user information do you need? You can always access the Thread.Current.Principal and get the user's name - and possibly use that to look up more info on the user in a database.
Or if you really really really need some piece of information at all times, you could implement your own custom principal deriving from IPrincipal (this is really not a big deal!), and add those bits of information there, and when the user logs in, create an instance of the MyCustomPrincipal and attach that to the current thread. Then it'll be available anywhere, everywhere, anytime.
Marc

I've had exactly the same issue, and have yet to find a satisfactory answer. All the options we've explored have had various issues. In the specific example you mention, you could obviously store that data in the session, as that would work for that example. There may be other scenarios, that we've had, where that may not work, but simple user info like that would be fine in the session.
We've just setup a BaseController that handles making sure that info is always set and correct for each view. Depending on how you're handling authentication, etc, you will have some user data available in HttpContext.User.Identity.Name at all times. Which can also be referenced.

Build a hierarchy of your models and put the shared information in the base model. This way it will be available to any view or partial view.
Of course it has to be retrieved on each request since web applications are not persistent.

You should store this in Session and retrieve it into your controllers via a custom ModelBinder.

Not sure if I get what you want to ask, but if you are looking for things like authentication and role-based authorization, actually ASP.net is providing a great framework to work on/start with.
This article (with also 2nd part) is something I recently discovered and read about which is really good start with the provider-pattern which help to understand the underlying authentication framework of ASP.net. Be sure to read about the membershipProvider class and the RoleProvider class in msdn also, they together make a great framework on most basic role-base authentication to work with (if you are comfortable with the function they provided, you even don't need to code data-access part, all are provided in the default implementation!)
PS: Check out Context.Users property too! It stores the current authenticated user information.

HttpContext.Current.Users.Identity returns the current user's information. Though I am not sure whether it gets passed implicitly when you make a webservice call.

Related

Endpoint design for a data retrieval orientated ASP.NET webapi

I am designing a system that uses asp.net webapi to serve data that is used by a number of jquery grid controls. The grids call back for the data after the page has loaded. I have a User table and a Project table. In between these is a Membership table that stores the many to many relationships.
User
userID
Username
Email
Project
projectID
name
code
Membership
membershipID
projectID
userID
My question is what is best way to describe this data and relationships as a webapi?
I have the following routes
GET: user // gets all users
GET: user/{id} // gets a single user
GET: project
GET: project/{id}
I think one way to do it would be to have:
GET: user/{id}/projects // gets all the projects for a given user
GET: project/{id}/users // gets all the users for a given project
I'm not sure what the configuration of the routes and the controllers should look like for this, or even if this is the correct way to do it.
Modern standard for that is a very simple approach called REST Just read carefully and implement it.
Like Ph0en1x said, REST is the new trend for web services. It looks like you're on the right track already with some of your proposed routes. I've been doing some REST design at my job and here are some things to think about:
Be consistent with your routes. You're already doing that, but watch out for when/if another developer starts writing routes. A user wants consistent routes for using your API.
Keep it simple. A major goal should be discoverability. What I mean is that if I'm a regular user of your system, and I know there are users and projects and maybe another entity called "goal" ... I want to guess at /goal and get a list of goals. That makes a user very happy. The less they have to reference the documentation, the better.
Avoid appending a ton of junk to the query string. We suffer from this currently at my job. Once the API gets some traction, users might want more fine grained control. Be careful not to turn the URL into something messy. Something like /user?sort=asc&limit=5&filter=...&projectid=...
Keep the URL nice and simple. Again I love this in a well design API. I can easily remember something like http://api.twitter.com. Something like http://www.mylongdomainnamethatishardtospell.com/api/v1/api/user_entity/user ... is much harder to remember and is frustrating.
Just because a REST API is on the web doesn't mean it's all that different than a normal method in client side only code. I've read arguments that any method should have no more than 3 parameters. This idea is similar to (3). If you find yourself wanting to expand, consider adding more methods/routes, not more parameters.
I know what I want in a REST API these days and that is intuition, discoverability, simplicity and to avoid having to constantly dig through complex documentation.

Membership Provider

I am currently developing an web site using asp and have a few questions regarding Membership Provider.
I am currently inheriting from Membership Provider class and have just got over the issue of only certain parameters being able to be passed to the CreateUser method.
I have been able to overcome this issue by creating a class that inherits from MembershipUser adding custom properties and then passing that the the UpdateUser method. However to me this seems quite messy and not very efficient as I am making two calls to the database when I could do it in one if I dont use the CreateUserWizard.
So my question is, is using the Provided Login components worthwhile if you are overriding the methods and require more parameters ect in order to keep the use of the properties you can define for this class in the web.config file or is it easier in the long run to just start from scratch. Basically what I want to know is how people have found using Membership by overriding and inheritance over starting from scratch, and how these compare.
Any webpages that talk about this would be good and apologies if the question doesn't make sense or I have missed anything out.
Thanks,
Ric
If I am understanding your question correctly, then yes the membership provider is a great api to build off of so you don't have to reinvent the wheel for the basics of authentication/authorization.
You are using Membership wrong. You should only create your own custom provider when you need to map onto an existing database. IF you are making your own database, then you should just use the default implementation.
Even if you create a custom implementation, you should not do anything that the current membership doesn't already provide. Just map those functions on to your database.
To add additional information, you create a secondary table called UserData or something. This table will be keyed by the MembershipUser.ProviderUserKey, so you lookup any data you need from the other table using the userid from the membership class.
You're really fighting upstream trying to change membership to give you custom things. You can do it, but why cause yourself trouble?

Best Practices for Passing Data Between Pages

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.

Asp.net Membership ProviderSql

I'm looking into Asp.net Membership Providership Sql to determine if it fits my needs and have a few basic questions.
It seems to create a lot of tables, many of them I don't think I need. I only need one application and no role management. Can I remove the unused tables or should I just leave them alone?
I need another table where I can associate records with the users created with the Sql membership provider. Is it safe to use the "Membership.GetUser.ProviderUserKey.ToString()" as the primary key for this user. I guess so, but it feels a bit like I'm depending on something that's out of my control since it's Asp.Net that manage it.
Also I'm going to access the database directly, without logging in with a user to get statistics. Is it safe to make Sql queries against the database using the aspnet_Users.UserId (table.field).
I guess what I'm afraid of is that suddenly after an framework update, Asp.Net changes the table layout or something.
Obviously, you can do whatever you want to it once you've generated the tables, but I think you should consider the ramifications of that. The Membership Provider framework works very well and is widely implemented. If you use their implementation, just use it and use the pieces you want and leave the rest alone.
They will be very careful when/if they make changes to it to either tell us of the breaking changes or not make any breaking changes.
The framework allows for you to override many of the provided methods, or you can simply write you own custom provider and base it heavily on the out of the box implementation.
ProviderUserKey is meant to store anything you would need to reference, so you can store a key to a record in your own database to store additional user information. I think it's OK to delete unrelated tables, as long as the features you use don't touch it.
I know it touches aspnet_applications, aspnet_users...
As a last resort, you can always create your own custom membership provider by creating a class that inherits from MembershipProvider.

ASP.NET built in user profile vs. old style user class/tables

I am looking for guidance regarding the best practice around the use of the Profile feature in ASP.NET.
How do you decide what should be kept in the built-in user Profile, or if you should create your own database table and add a column for the desired fields? For example, a user has a zip code, should I save the zip code in my own table, or should I add it to the web.config xml profile and access it via the user profile ASP.NET mechanism?
The pros/cons I can think of right now are that since I don't know the profile very well (it is a bit of a Matrix right now), I probably can do whatever I want if I go the table route (e.g., SQL to get all the users in the same zip code as the current user). I don't know if I can do the same if I use the ASP.NET profile.
Ive only built 2 applications that used the profile provider. Since then I have stayed away from using it. For both of the apps I used it to store information about the user such as their company name, address and phone number.
This worked fine until our client wanted to be able to find a user by one of these fields.
Searching involved looping through every users profile and comparing the information to the search criteria. As the user base grew the search time became unacceptable to our client. The only solution was to create a table to store the users information. Search speed was increased immensely.
I would recommend storing this type of information in its own table.
user profile is a nice clean framework for individual customization(AKA. Profile Properties). (e.g. iGoogle)
the problem of it is its not designed for query and not ideal for data sharing to public user.(you still would be able to do it, with low performance)
so, if you want to enhance the customized user experience, user profile would be a good way to go. otherwise, use your own class and table would be a much better solution.
In my experience its best to keep an the info in the profile to a bare minimum, only put the essentials in there that are directly needed for authentication. Other information such as addresses should be saved in your own database by your own application logic, this approach is more extensible and maintainable.
I think that depends on how many fields you need. To my knowledge, Profiles are essentially a long string that gets split at the given field sizes, which means that they do not scale very well if you have many fields and users.
On the other hand, they are built in, so it's an easy and standardized way, which means there is not a big learning curve and you can use it in future apps as well without needing to tweak it to a new table structure.
Rolling your own thing allows you to put it in a properly normalized database, which drastically improves performance, but you have to write pretty much all the profile managing code yourself.
Edit: Also, Profiles are not cached, so every access to a profile goes to the database first (it's then cached for that request, but the next request will get it from the database again)
If you're thinking about writing your own thing, maybe a custom Profile Provider gives you the best of both worlds - seamless integration, yet the custom stuff you want to do.
I think it is better off using it for supplementary data that is not critical to the user that is only normally important when that user is logging in anyway. Think data that would not break anything important if it was all wiped.
of course thats personal preference but others have raised some other important issues.
Also very useful considering it can be used for an unauthenticated user whose profile is maintained with an anonymous cookie.

Resources