Audit and log, all or selective, user input on ASP.NET web application. How would you? - asp.net

I'm building UI logging into a long-existing ASP.NET enterprise application. I have my own ideas of how to progress from here and am continuing to research & design. But I'd love to hear some details from the SO community.
Here are the details, assumptions and questions as of right now, subject to evolve within the enterprise as well as whatever input comes in here on SO:
Would prefer to have a consistent DB connection since there will be a lot of activity
Will probably use the ThreadPool, but will this conflict too much with ASP.NET vying for threads?
Possibly use in-memory queue (Queue) for logging batches of inputs periodically? (one per domain)
Will need to be configurable. IE: Could log all page events during their normal postback calls, or hook individual control actions or events to being logged whether there's a postback or not. IE: User collapses a panel.
All "high-visibility" UI events that'll already be posting back as well as other events that won't necessarilly post back right away. Have a client batch of events and send occasionally?
How do we minimize the impact on existing code?
Have "fly on the wall" AJAX functionality that posts back accordingly? It'll basically be watching all that's been configured to be logged.
Logging must be ordered for reporting a user's step-by-step progress from point A to B in a workflow.

How about a WCF service that does the actual logging, paired with a PostSharp attribute. In your PostSharp attribute you can call asynchronously to you WCF service while your application hums along. I've implemented something like this in past projects and it works great with little if no slowing down.
http://www.postsharp.org/

Why not use log4net? You could capture a userid, sessionid, and any additional information you need to track step-by-step progress. You could configure the levels so that you could reduce the logging if it impacted performance. I wouldn't consider re-inventing the wheel by writing your own framework when there are several viable existing logging frameworks.

Related

ASP.NET: How to limit access to a page to just one user?

How to restrict the page by accessing only one user at a time. Using asp.net can i use global.asax, is there any other way to restrict, if one user accessing the page, another user not able to access that page. we have to give message that one user is accessing the page. is it possible. can you help me or give some reference.
Although there are probably many better ways of dealing with this sort of problem, I'm going to assume that you do actually need this.
What I would do:
Make your application so that when the page is loaded(when it isn't "locked"), it logs to a database that the page was loaded and "lock" it. In the actual page, I'd have some kind of AJAX to constantly poll the web server every 5-15 seconds to tell your application the user is still on the page. And then make it so that the page becomes unlocked after 5-15 seconds from the time saved to the database by the last AJAX call.
Again, I really suspect that there is a better way around an issue like this, but this is a direct answer to your question
Based on this:
yeah sure, jupaol, it is depend on accounts, in my web application, one report has to approve only one user, but the approve authority having two users. if both of them accessing the same page and approve at a time, it will big mess. here i an not using database.
The problem is related with concurrency, there are several ways to face an issue like this, for example the easiest one is to use optimistic concurrency. Even when you are not using a database for this, you can emulate it.
You should be storing the result of the approvers somewhere, in order to mark the report as approved, with this in mind you should be able to do something like this:
Before render the page get the latest report status
If the report has not been approved, render normally
If the report was approved seconds before, render it in read-only mode reporting who approved it (or similar approach)
Add a validation to your ChangeStatus method, in this method do the following:
Get the latest status of the current report
If the report is still not validated, then block the thread (you could use a Mutex or similar) and mark the report as validate it
If the report was already validate it, raise a domain exception and handle it in your page correctly (perhaps render the page in read-only mode explaining that the report was already validate it)
If you want a more responsive application, (RIA), you might want to consider the following approaches:
Perhaps this would be the worst approach but it's still an option, you could keep a log tracking when a user request your page, then in subsequent requests check if the log is still valid, if it is not, then redirect to another page indicating the page is in use, otherwise allow access to the page. I believe this is an error-prone approach because you would be relying on this simple validation in order to prevent an inconsistency in your system, besides you would have the polling problem described in the following approach
Using AJAX to poll data from a service checking if the report has been approved. Perhaps this is the easiest way to accomplish this but it is not recommended it, because you would be polling your server constantly, and eventually you would have scalability problems
You could use Comet to get notified to the browser (client) whenever a server event has occurred, in this case when your report has been approved. The problem with this approach is that you have to keep an opened connection with the server in order to get notified.
The last approach and the most recommended these days is to use Web Sockets, this is the technology used in StackOverflow to get notifications in real time.

Can an ASP.NET application handle NServiceBus events?

Most if not all of the NSB examples for ASP.NET (or MVC) have the web application sending a message using Bus.Send and possibly registering for a simple callback, which is essentially how I'm using it in my application.
What I'm wondering is if it's possible and/or makes any sense to handle messages in the same ASP.NET application.
The main reason I'm asking is caching. The process might go something like this:
User initiates a request from the web app.
Web app sends a message to a standalone app server, and logs the change in a local database.
On future page requests from the same user, the web app is aware of the change and lists it in a "pending" status.
A bunch of stuff happens on the back-end and eventually the requests gets approved or rejected. An event is published referencing the original request.
At this point, the web app should start displaying the most recent information.
Now, in a real web app, it's almost a sure thing that this pending request is going to be cached, quite possibly for a long period of time, because otherwise the app has to query the database for pending changes every time the user asks for the current info.
So when the request finally completes on the back-end - which might take a minute or a day - the web app needs, at a minimum, to invalidate this cache entry and do another DB lookup.
Now I realize that this can be managed with SqlDependency objects and so on, but let's assume that they aren't available - perhaps it's not a SQL Server back-end or perhaps the current-info query goes to a web service, whatever. The question is, how does the web app become aware of the change in status?
If it is possible to handle NServiceBus messages in an ASP.NET application, what is the context of the handler? In other words, the IoC container is going to have to inject a bunch of dependencies, but what is their scope? Does this all execute in the context of an HTTP request? Or does everything need to be static/singleton for the message handler?
Is there a better/recommended approach to this type of problem?
I've wondered the same thing myself - what's an appropriate level of coupling for a web app with the NServiceBus infrastructure? In my domain, I have a similar problem to solve involving the use of SignalR in place of a cache. Like you, I've not found a lot of documentation about this particular pattern. However, I think it's possible to reason through some of the implications of following it, then decide if it makes sense in your environment.
In short, I would say that I believe it is entirely possible to have a web application subscribe to NServiceBus events. I don't think there would be any technical roadblocks, though I have to confess I have not actually tried it - if you have the time, by all means give it a shot. I just get the strong feeling that if one starts needing to do this, then there is probably a better overall design waiting to be discovered. Here's why I think this is so:
A relevant question to ask relates to your cache implementation. If it's a distributed or centralized model (think SQL, MongoDB, Memcached, etc), then the approach that #Adam Fyles suggests sounds like a good idea. You wouldn't need to notify every web application - updating your cache can be done by a single NServiceBus endpoint that's not part of your web application. In other words, every instance of your web application and the "cache-update" endpoint would access the same shared cache. If your cache is in-process however, like Microsoft's Web Cache, then of course you are left with a much trickier problem to solve unless you can lean on Eventual Consistency as was suggested.
If your web app subscribes to a particular NServiceBus event, then it becomes necessary for you to have a unique input queue for each instance of your web app. Since it's best practice to consider scale-out of your web app using a load balancer, that means that you could end up with N queues and at least N subscriptions, which is more to worry about than a constant number of subscriptions. Again, not a technical roadblock, just something that would make me raise an eyebrow.
The David Boike article that was linked raises an interesting point about app pools and how their lifetimes might be uncertain. Also, if you have multiple app pools running simultaneously for the same application on a server (a common scenario), they will all be trying to read from the same message queue, and there's no good way to determine which one will actually handle the message. More of then than not, that will matter. Sending commands, in contrast, does not require an input queue according to this post by Udi Dahan. This is why I think one-way commands sent by web apps are much more commonly seen in practice.
There's a lot to be said for the Single Responsibility Principle here. In general, I would say that if you can delegate the "expertise" of sending and receiving messages to an NServiceBus Host as much as possible, your overall architecture will be cleaner and more manageable. Through experience, I've found that if I treat my web farm as a single entity, i.e. strip away all acknowledgement of individual web server identity, that I tend to have less to worry about. Having each web server be an endpoint on the bus kind of breaks that notion, because now "which server" comes up again in the form of message queues.
Does this help clarify things?
An endpoint(NSB) can be created to subscribe to the published event and update the cache. The event shouldn't be published until the actual update is made so you don't get out of sync. The web app would continue to pull data from the cache on the next request, or you can build in some kind of delay.

Looking for guidance on WF4

We have a rather large document routing framework that's currently implemented in SharePoint (with a large set of cumbersome SP workflows), and it's running into the edge of what SP can do easily. It's slated for a rewrite into .NET
I've spent the past week or so reading and watching WF4 discussions and demonstrations to get an idea of WF4, because I think it's the right solution. I'm having difficulty envisioning how the system will be configured, though, so I need guidance on a few points from people with experience:
Let's say I have an approval that has to be made on a document. When the wf starts, it'll decide who should approve, and send that person an email notification. Inside the notification, the user would have an option to load an ASP.NET page to approve or reject. The workflow would then have to be resumed from the send email step. If I'm planning on running this as a WCF WF Service, how do I get back into the correct instance of the paused service? (considering I've configured AppFabric and persistence) I somewhat understand the idea of a correlation handle, but don't think it's meant for this case.
Logging and auditing will be key for this system. I see the AppFabric makes event logs of this data, but I haven't cracked the underlying database--is it simple to use for reporting, or should I create custom logging activities to put around my actions? From experience, which would you suggest?
Thanks for any guidance you can provide. I'm happy to give further examples if necessary.
To send messages to a specific workflow instance you need to set up message correlation between your different Receive activities. In order to do that you need some unique value as part of your message data.
The Appfabric logging works well but if you want to create custom a custom logging solution you don't need to add activities to your workflow. Instead you create a custom TrackingParticipant to do the work for you. How you store the data is then up to you.
Your scenario is very similar to the one I used for the Introduction to Workflow Services Hands On Lab in the Visual Studio 2010 Training Kit. I suggest you take a look at the hands on lab or the Windows Server AppFabric / Workflow Services Demo - Contoso HR sample code.

Need guidance on getting data to Silverlight app via ASP.NET/WCF

First of all thank you for any help. I have looked extensively and haven't found a sure solution, so here I am...
Basically I am developing an asp.net (4.0) app. One webform represents a report and is divided into two pieces:
- a div that acts like a control panel which contains textboxes, comboboxes, calendars, etc. which provide parameters for a query, and a button to get the data.
- a div that holds the silverlight control host. The silverlight app only contains a custom datagrid control.
So, as you would imagine, the user provides values for the parameters and clicks the button to get the data into the silverlight app's custom datagrid control.
-I know what you're probably asking yourself, why don't I just add the controls to the silverlight app and use RIA services. Without going into too much detail, we want a newer datagrid that we can slap into some of our existing asp.net pages.
I don't know what is the best practice for something like this. I've looked extensively and there are several options I have considered and even got my feet wet experimenting (with no success).
What I think I would like to do is have a wcf service that only sends data to the silverlight client on the page.
Let me be clear that I do not need a request/reply message exchange pattern because the silverlight client isn't going to be making any requests.
In my "quest" to accomplish this I have found examples/tutorials on duplex messaging which I think might work well if I can set the asp page as a client to the service and the silverlight app as a client to the same service.
The use clicks the button and the asp page's service reference calls the service to get the data and then in turn it sends the data to the silverlight client.
One concern I have is that all of the tutorials I have found send the messages to all of the clients, so what if two people are visiting the site at the same time? Would it update both of thier sl apps? How would I target the right client?
So my question is can anyone provide any advice, links, or other resources for a solution to this scenario?
First off, I don't think you need Silverlight. There are a ton of great UI controls out there like Telerik RadGrid that you could drop into your existing app and be up and running in an hour or two.
Having said that, if you really want to make this work, what you need is pub/sub that works both in the browser and in Silverlight. Take a look at PubNub. You get 5,000 messages per day for free, and works in virtually any client (phone, Silverlight, browser, etc) with a simple API.
Basically, your Silverlight client would subscribe to a "channel" to be notified when the filter parameters change, and your form would publish messages to this channel, either through JavaScript or server side, telling subscribers (1 in your case) of changed filter values. When the Silverlight client is notified, it would make a request for data via WCF.
Bit of a hack though. I would encourage you to drop the Silverlight and use an AJAX grid. Hope this helps!

Communication between pages

I want to enable an user to be able to communicate with other users through a site. I know that ASP.net is stateless, but what can I use for this synced communication? Java servlets?
I don't think you need to set up Java just to use a servlet for this. I would use AJAX and the database. I don't know ASP.NET but I PHP is similar in this case, being also basically "stateless". If you want to display some kind of asynchronous communication between two different users, say, from two different sessions, without a lot of refreshing (like chat), you can have the AJAX page constantly poll the database for new messages, and display them when they come in. You can also use AJAX to insert the new messages, giving the user read/write access to this messages data structure. Since the "other" user is doing the same thing, user A should see new messages pop up when user B types them in.
Is that what you mean?
You probably don't want to use sessions for things like chat messages but you probably could use some type of implementation of queueing using MSMQ.
The approach to chat could be done in many different ways, this is just a suggesting off the top of my head.
Could do a messaging solution in Java Servlets using the application context. Objects stored as attributes in the application context are visible from anywhere in your webapp.
Update: Chat like functionality... I guess that would be AJAX polling your message structure stored in the app context unless you want to use something like applets.
Don't know if it's any good, but there's a chat servlet here that might be useful to use or learn from if you decide to go the Java route...
ASP.NET is "stateless" but it maintains state using Sessions. You can use them by default just using the Session[] keyword.
Look at ASP.NET Session State for some details from Microsoft.

Resources