Communication layer between client and server - c#

I'd like to know if there is any technology to control communications between the client and the server in a web application (ASP.NET)
Example:
Number of requests
Check that no repeat a request
Check that an operation was performed
WorkFlow
The client sends the request "A"
The server receives the request "A", and responds
The server marks the request "A" as answered
The client resends the request "A"
The server answers that the request "A" was answered

You could intercept the request in the following method, in the Global.asax file:
protected void Application_BeginRequest(object sender, EventArgs e)
{
var request = ((System.Web.HttpApplication)(sender)).Context.Request;
//here you can evaluate and take decisions about the request
}

In any ASP.NET application you can use the HttpApplication events to track the needed changes. For example, you could track it using the BeginRequest and/or EndRequest events:
protected void Application_BeginRequest(object sender, EventArgs e)
{
if(MyGlobalFlags.TrackingRequests){
// do stuff
}
}
protected void Application_EndRequest(object sender, EventArgs e)
{
if(MyGlobalFlags.TrackingRequests){
// do stuff
}
}
By personal opinion, I would use a globlal flag that I could turn off easily if I wanted.
If you are talking about an ASP.NET MVC application, I would also recommend using ActionFilters in the actions you want to track. You could implement your own ActionFilter class and track those changes OnActionExecuted and/or OnResultExecuted. I would still use the global flag to turn off the tracking without changing code.
public class MyTrackingActionFilter: ActionFilterAttribute{
public override OnActionExecuted(ActionExecutedContext filterContext)
{
if(MyGlobalFlags.TrackingRequests){
// do stuff
}
}
public override OnResultExecuted(ActionExecutedContext filterContext)
{
if(MyGlobalFlags.TrackingRequests){
// do stuff
}
}
}
As a note, I wouldn't try to do heavy stuff in these events. If the track requires heavy database manipulation that can run in parallel, I recommend you to use a queue system while using the thread pool.

Related

Recording events(request & response) in an MVC application

Ok, so I have quite a task here:
The background of this project is very complex and fully covered by NDA's so I'll just state what I am trying to do without the background.
So what I need is a way to record every request made to an MVC application and every response from it.
Furthermore, I also need a way to "reply" the requests exactly as they were sent.
I was hoping that I could create some solution that "loads" the MVC application, Self hosts or runs in IIS, get requests, records them and passed them verbatim to the MVC application which would then act exactly like any other MVC app.
I could then create a second solution that "loads" the MVC app but instead of opening it up to request it would read the events from the event store and "replays" them in the MVC app.
Now I have no clue where to even start. This kinda thing is way out of my comfort zone.
If there is another solution for how I can record and replay request (and responses) then please let me know.
Even if there is a way to intercept a request in MVC before it starts doing all of its authentication and routing malarkey then that would be a great starting point. I would also need to know where I can capture the response at the very last second before it is sent.
Many thanks for your time
Andy
A HttpModule would work just fine for your scenario:
using System;
using System.Web;
public class HelloWorldModule : IHttpModule
{
public HelloWorldModule()
{
}
public String ModuleName
{
get { return "HelloWorldModule"; }
}
// In the Init function, register for HttpApplication
// events by adding your handlers.
public void Init(HttpApplication application)
{
application.BeginRequest +=
(new EventHandler(this.Application_BeginRequest));
application.EndRequest +=
(new EventHandler(this.Application_EndRequest));
}
private void Application_BeginRequest(Object source,
EventArgs e)
{
// Create HttpApplication and HttpContext objects to access
// request and response properties.
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
/*...*/
}
private void Application_EndRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
/*...*/
}
public void Dispose() { }
}
The code and more information available here.

How do I get log4net logging info in Global.asax that comes from another .aspx page?

I have an .aspx page with some synchronous code that's taking a very long time to execute and is triggering a request timeout. For example:
protected void Page_Load(object sender, EventArgs e)
{
var log = LogManager.GetLogger("test");
log.Debug("Before thread sleep...");
Thread.Sleep(99999999);
log.Debug("After thread sleep.");
}
In my Global.asax, I've added some error handling that will e-mail out any exceptions:
protected void Application_Error(Object sender, EventArgs e)
{
var exception = HttpContext.Current.Server.GetLastError();
SendExceptionEmail(exception);
}
Problem is, in Global.asax, I only have access to the request and response and the exception that occurred, but not the output from the logger. How do I get access to this in Global.asax? Without it, I can't tell what piece of code is hanging the application without digging through the log files, which is a major chore to filter.
The 'log' object is a static variable, and it is not correct to try to fetch it in Global.asax Application_Error(). Depending on the current thread in thread pool, you might get unpredictable values in it.
A more secure approach could be along with log.Debug() to insert some Debug data into HttpContext.Current.Items. Then you can access these items in Application_Error() method.
Context.Items are considered as thread-safe and are recommended for use in cases like this.
Another way to do it would be to have log4net send the email for you using an email appender. See this example: http://sradack.blogspot.co.uk/2007/09/have-log4net-send-email-when-error.html

Is HttpContext.RemapHandler supposed to change which handler processes request?

The MSDN documentation says:
HttpContext.RemapHandler Method - Enables you to specify a handler for the request.
I am trying to move the processing of the request from one handler to another depending on a condition in the first handler. The HttpContext.RemapHandler method seems to initialise an instance of the second handler but not call the HttpHandler.ProcessRequest method; the response is empty.
Does the HttpContext.RemapHandler method do what I think it should - transfer processing to a new HttpHandler and calling the HttpHandler.ProcessRequest method? Or should I be using another approach such as another method or an HttpModule?
EDIT:
Turns out I should be using a HTTPHandlerFactory. I have the solution working nicely now.
So what exactly is HttpContext.RemapHandler for?
You can use HttpContext.RemapHandler as you specified, however if another HttpHandler calls RemapHandler (e.g. ASP.NET MVC which registers MvcHandler in PostResolveRequestCache) your IHttpModule will never fire. This is maybe why IHttpHandler.Process was never called.
If this is your issue, you can simply define a route to ignore in MvcApplication.RegisterRoutes like this:
routes.IgnoreRoute("your_path/{*pathInfo}");
Also, remember that with Visual Studio Web Development Server and IIS6, RemapHandler will not work.
Here is an example of how to select the right way to remap the handler based on whether or not Integrated Pipeline is activated AND still be able to access the session:
public void Init(HttpApplication application)
{
if (HttpRuntime.UsingIntegratedPipeline)
// For IIS 7 and IIS 8
application.PostAuthorizeRequest += Application_PostAuthorizeRequest;
else
// For IIS 6
application.PostMapRequestHandler += Application_PostMapRequestHandler;
}
private void Application_PostAuthorizeRequest(object sender, EventArgs e)
{
((HttpApplication)sender).Context.RemapHandler(_myHandler);
}
private void Application_PostMapRequestHandler(object sender, EventArgs e)
{
((HttpApplication)sender).Context.Handler = _myHandler;
}
The difference between using a HttpHandlerFactory and HttpModule in this case is that the latter allows you to decide when to use which IHttpHandler regardless of ASP.NET IHttpHandler mappings. More on MSDN: HTTP Handlers and HTTP Modules Overview.

ASP.NET Updating a UpdatePanel on another client

Okay.
So basically i am working on a message system on a webpage.
Users on my webpage is able to send each other messages, but now i want the messages to "pop up" on the receivers screen when sent. Exactly like when somebody on facebook sends you a message while your online, the message thing goes red. To solve my problem i need every client to know which other clients are online at the moment. I have solved this by coding an Observer-like pattern in my Global.asax:
public static void AddObserver(Observer o)
{
if(!observers.Contains(o))
observers.Add(o);
System.Diagnostics.Debug.WriteLine("Observer tilføjet : " + observers.Count);
}
public static void RemoveObserver(Observer o)
{
if (observers.Contains(o))
observers.Remove(o);
System.Diagnostics.Debug.WriteLine("Observer fjernet : " + observers.Count);
}
public static void NotifyObserversNewMail(Observer observer)
{
foreach (Observer o in observers)
if(!o.Equals(observer))
o.UpdateNewMail();
}
And the observer in this case i simply the Site.Master, which i have made extend the Observer class :
public partial class SiteMaster : System.Web.UI.MasterPage, Observer
{
protected void Page_Unload(object sender, EventArgs e)
{
Session["observer"] = this;
Global.AddObserver(this);
}
protected void Page_Load(object sender, EventArgs e)
{
//ADD OBSERVER TO GLOBAL.ASAX
if (Session["observer"] != null)
Global.RemoveObserver((Observer)Session["observer"]);
public void Update()
{
DLMessages.DataSource = ServiceMessages.GetInstance().GetMessages();
DLMessages.DataBind();
UPMessages.Update();
}
Where DLMessages is a DataList inside the UpdatePanel UPMessages.
So we have a "sender" client, and a "receiver" client.
When the sender creates a new message this method gets called:
protected void MessageSend(object source, EventArgs args)
{
Page.Validate("ValGroupMessageTo");
if (Page.IsValid)
{
ServiceMessages.GetInstance().SendMessage(ServiceCommunity.GetInstance().GetUser(MessageTo.Text).Id, ((User)Session["user"]).Id, MessageMessage.Text);
Global.NotifyObserversNewMail((Observer)Session["observer"]);
ClosePopups(new object(), new EventArgs());
Update();
}
}
As you can might notice it calls the Notify on global.asax, and the update() directly on itself. The UpdatePanel on the "sender" side updates perfectly, but on the receiver side nothing happens. Not in the UpdatePanel anyways.
Cause if i alter the code in the Update() to run through the messages from the DB, i can see that the message gets called fine, and the new message is loaded. Just not updated to the UpdatePanel.
So i have been thinking a lot about why the updatepanel doesnt get updated on the "receiver" side when the data gets updated, and my conclusion is it is because theres no partial postback on the "receiver" side. Yeah sure, the Update() method gets called, but theres no postback. So my question is this:
Is it possible to "force" a partial post back from the code-behind? Or is there another solution that might work better?
Hope it makes sense :-)
Do yourself a favour and build the whole thing using SignalR. It is a library for real time communication between the server and the browser for .NET (includes client-side libraries).
If you insist on doing it the hard way you should use a timer to trigger the update panel update
I'm not a big fan of working with updatepanels, but I think you can use the timer-control to force a partial postback.
Have a look at: http://mattberseth.com/blog/2007/08/using_the_ajax_timer_control_a.html
Those solutions, comet etc will work but really your best bet is to use socket.io
Real Time Browser Applications
You could also combined it with backbone.js and have a really nice app. I helped make a real time web messenger based on these 2.
I'm not an expert but you could try the Javascript/Jquery SetTimeout function associated with a WebService (.svc) to make periodic request from the client and retrieve data from the server.

How would an HttpModule for Custom Authentication interact with Windows Authentication?

I am trying to create a custom HttpModule which controls which users can view a site.
I am trying to leverage Windows Authentication to do this.
On an individual page, I would probably do something like this:
if (HttpContext.Current.User.Identity.Name.Contains("jsmith"))
{
Response.Write("You do not have the correct permissions to view this site.");
Response.End();
}
But because I want to make this more configurable at the application level, I would like to use an HttpModule.
Here is the start that I have made on the code:
using System;
using System.Web;
public class CustomAuthHttpModule : IHttpModule
{
public void Dispose() { }
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(OnBeginRequest);
context.EndRequest += new EventHandler(OnEndRequest);
}
void OnBeginRequest(object sender, EventArgs e) { }
void OnEndRequest(object sender, EventArgs e)
{
HttpApplication appObject = (HttpApplication)sender;
HttpContext contextObject = appObject.Context;
if (contextObject.User.Identity.Name.Contains("jsmith"))
{
contextObject.Response.Clear();
contextObject.Response.End();
}
}
}
I would be fine with using the code I have, if I could put it in the OnBeginRequest() function. But the User property is not created in the HttpContext object until OnEndRequest() runs.
Running the code earlier would prevent the application from doing the extra work of producing this output, since some users are just going to be blocked from access in the end.
Can someone suggest a solution to this - is this happening because my module is running before the Windows Auth module, or what?
... or, maybe there is an easier way to do what I am trying to do with IIS or file system permissions?
You want the AuthenticateRequest event.
AuthenticateRequest event
Have you tried to implement the method in the global.aspx? OnSessionStart?
Besides I would use hasRole or some other group-Property instead of contains and username.
Why write an http module for this. If this is asp.net web forms then why not simply use built in stuff like LoginView http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.loginview.aspx

Categories

Resources