MVC web application and void methods - c#

I'm working on an application and i want to understand it's behavior.
Once i have already logged into the system i make one request through ajax to the back-end, it's a void method that will process some information and feed a table.
Meanwhile i have another tab, also in the same session as the one that called the void method, and i want to go to the system's dashboard, so i press the corresponding button in the menu. This second tab will ONLY go to the dashboard when the void method is done.
Why? I would need static webservices to do that for me? I assumed that once it's a void method and i don't need its answer that would work.

You need to provide more details about the state of the application during the execution and the conditions around your requests.
If you're using AJAX to call the backend method and it doesn't return anything, your second request in the other tab should process normally. Web Applications are usually capable of handling multiple requests almost simoultaneously (barring any DDoS attack or unusually high load limits reached), so one thing i would ask is ¿are you debugging the application while sending the second request?, if you have a breakpoint on the server method that's being called and it's being hit by your first request, you need to step out of that execution manually before you can process the next request.
Another thing you might want to review is, if this method is a very resource/time-consuming operation, you might want to use tasks or threads to avoid creating bottlenecks between requests.

Related

WCF REST - Is it possible to return response without ending the execution?

As you'll most likely figure it out, I'm not very experienced with async operations in general (only used Android's AsyncTask).
This is the outline of a WCF REST POST method; I'll use this image to hopefully explain what I'm trying to achieve.
The FirstJob saves some stuff to the database.
SecondJob reads what was saved in the database and does some work with the data.
The client does not care about what happens in SecondJob and just wants to receive the response from FirstJob.
So the two jobs don't need to run in parallel as SecondJob depends on FirstJob; the SecondJob would ideally run in a separate thread/context(?) or similar.
From what I've noticed, the second job does start in a separate thread, the execution reaches the return statement while the 2nd job is running, but the request does not end until SecondJob finishes.
I'd personally treat the second job as a separate POST operation and call the second job POST from the controller. The controller is the controller for the first job and can return the correct status from the first job; it just happens to call a POST out to a second endpoint while doing it.
The benefit of this approach is that the second job doesn't even need to be on the same IIS (in an NLB farm it could be anywhere) so you get load balancing thrown in for free. Alternatively the "second job server" can be on a specific URL reserved just for this kind of background processing task.
I suggest you not to rely on the IIS to handle your background task as it can shut down it without waiting. I suggest you to create a windows service application, which will accept the requests for a second jobs, via another WCF binding or database requests or something else.
You can get the results of the second jobs with another request from your controller, as #PhillipH stated.
The thing I was trying to do was actually working in the first place, but the visual studio debugger fooled me. I tested again without the debugger, but with a Tread.Sleep(60000) and it looks like it behaves as expected. The SecondJob keeps running in the background after the api call returned the response.

Run asynchronous operation in one controller method and get that operation's result in another

I have a long running operation you might read in couple of my another questions (for your reference here is first and second).
In the beginning of whole deal, project expose a form in which user should specify all necessary information about XML file and upload XML file itself. In that method all user input data caught and went to an WCF service that handles such king of files. Controller got only task id of such processing.
Then user got redirected to progress bar page and periodically retrieves status of task completeness, refreshes the progress bar.
So here is my issue comes. When processing of XML file if over, how can I get results back and show them to user?
I know that HTTP is stateless protocol but there is cookie mechanism that could help in this situation. Of course, I may just save processing results to some temporary place, like a static class in WCF server, but there is a high load on service, so it will eat all of supplied memory.
In other words, I would like to pass task to WCF service (using netNamedPipeBinding) and receive results back as fast as it really possible. I want to escape temporary saving result to some buffer and wait until client will gather it back.
As far as I go is using temporary buffer not on service side but at client's:
using (XmlProcessingServiceClient client = new XmlProcessingServiceClient())
{
client.AnalyzeXmlAsync(new Task { fileName = filePath, id = tid });
client.AnalyzeXmlCompleted += (sender, e) =>
{
System.Web.HttpContext.Current.Application.Lock();
// here is I just use single place for all clients. I know it is not right, it is just for illustrating purposes.
System.Web.HttpContext.Current.Application["Result"] = e;
System.Web.HttpContext.Current.Application.UnLock();
};
}
I suggest you to use a SignalR hub to address your problem. You have a way to call a method on the client directly to notify the operation completed. And this happen without having to deal with the actual infrastructure trouble there is in implementing such strategies. Plus SignalR plugs easily in an asp.net MVC application.
To be honest I didn't really get the part about the wcf server and stuff, but I think I can give you more of an abstract answer. To be sure:
You have a form with some fields + file upload
The user fills in the form and supplies an XML file
You send the XML file to an WFC services which procress it
Show in the mean time a progress bar which updates
After completion show the results
If this is not want you want or this is not what your question is about you can skip my answer, otherwise read on.
Before we begin: Step 3 is a bit ambiguous: It could mean that we send the data to the service and wait for it to return the result or that we send the data to the service and we don´t wait for it to return the result.
Situation 1:
Create in a view the form with all the required fields
Create an action in your controller which handles the postback.
The action will send the data to the service and when the service returns the result, your action will render a view with the result.
On the submit button you add an javascript on click event. This will trigger an ajax call to some server side code which will return the progress.
The javascript shows some sort of status bar with the correct progress and repeats itself every x seconds
When the controller finishes it will show the result
Situation 2:
-
-
After sending the data to the service the controller shows a view with the progress bar.
We add an javascript event on document ready which checks the status of the xml file and updates a progressbar. (same as the onclick event in step 4 in situation 1)
When the progressbar reaches 100% it will redirect to a different page which shows the results
Does this answer your question?
Best regards,
BHD
netNamedPipeBinding will not work for cross-machine communication if this is what you have in mind.
If you want to host our service on IIS then you will need one of the bindings that use HTTP as their transport protocol. Have a look at the duplex services that allow both endpoints to send messages. This way the server can send messages to the client anytime it wishes to. You could created a callback interface for progress reporting. If the task is going to take a considerable amount of time to complete, then the overhead of the progress reporting through HTTP might be ok.
Also have a look at Building and Accessing Duplex Services if you want to use a duplex communication over HTTP with Silverlight (PollingDuplexHttpBinding).
Finally you could look for a Comet implementation for ASP.NET. In CodeProject you will at least a couple (CometAsync and PokeIn).
I'm not sure if this is the best solution but I was able to do something similar. This was the general setup:
Controller A initialized a new class with the parameters for the action to be performed and passed the user's session object
The new class called a method in a background thread which updated the user's session as it progressed
Controller B had json methods that when called by client side javascript, checked the user's session data and returned the latest progress.
This thread states that using the session object in such a way is bad but I'm sure you can do something similar with a thread safe storage method like sql or a temp file.

WCF Rest Asynchronous Calling Methods

I have a class library I developed that is rather processing intensive that I currently call through a WCF REST service.
The REST service directly accesses the DLLs for the class library and more or less the WCF rest service is an interface for the system.
Let's say the following methods are defined:
Create Request
Starts a thread that takes five minutes, but immediately returns a session ID that the process generates and the thread uses to report when it is completed to the database.
Check Status
Accepts a session id and checks the database to see if the process has completed.
I have to think that there is a better way to "manage" the threads running, however, my requirements state that the user should receive an immediate response from the REST service upon issuing a request.
I am using the WCF Message property to return XML to the browser and as this application can be called from any programming language I can't use classic WCF and callbacks (I think, correct me if I am wrong).
Sometimes I run into an issue where an error occurs and the iscomplete event never gets written to the database and therefore the "Check Status" method says it's processing forever.
Does anyone have any ideas about what is normally done and what can be done in this situation?
Thanks!
Jeffrey Kevin Pry
Your service should return a 202 Accepted at the initial request with a way for the client to check the current status, either through the Location header or as part of the content.
As you indicate the client then polls the URL indicated to check the current status. I would also suggest adding a bit of cache time to this response in case a client just starts looping.
How you handle things on the server is up to you and in no way related to REST. For one thing I would put all logic that executes as the background thread in a try/catch to you can return an error status back if an error occurs and possibly retry the action depending on the circumstances.
I implemented a similiar process for importing/processing of large files and to be honest, I have never had a problem. Perhaps resolving the reason that the IsComplete never gets set will make this more resilient.
Not much of an answer, but still..

WCF / ASP.NET - protected against misuse such as DOS

We currently host a lengthy form on our ASP.NET website, which makes use of a public facing facade WCF service to submit information over SSL into our network through a number of other facade services, etc.
We've experienced some issues with downtime on the service chain, and because of this some users have been very frustrated that they complete the lengthy form, only to find out after the fact that the service isn't up. Because of this, we are implementing a type of ping functionality on the form that will ping the service before the form is started, to ensure the service is up.
If the Ping() method is simply called during OnLoad of the form web page, there is potential for DOS attacks through for example a script that continually makes HTTP GET requests against the page.
My question is - From a conceptual level, what is the best way to ensure human interaction with the page while keeping it useable. For example, a CAPTCHA before the Ping() is called and form is started is way too intrusive even though it would be effective at ensuring the form is used properly. On the other hand simply allowing Ping() to fire OnLoad is far too risky for attacks.
One option I've considered is to have a button available to users which allows them to verify service availability and enable the form in one shot. This would at least be a balance between the two. I'm asking for your input on ideas for how best to balance this approach. Any asp.net, c#, or javascript/ajax based answers are fine.
Lastly - I also know there are flaws to this approach of checking service availability as there is no guarantee the service will be available by the time the form is filled out - but the decision has been made to use this approach so please keep your answers on point.
Thanks for the help and input in advance!
UPDATE 1:
In response to Josh's answer below - I should clarify that the form data submitted is sensitive and cannot be cached on the server or stored locally for later submission if the service fails. This is why it is very important to give the user a preemptive heads up. The issues we've had with the services are not intermittent so if the Ping() comes back true, there is an extremely good chance the user will not experience issues submitting the form a few minutes later.
UPDATE 2:
The Ping() Method is currently a server-side c# method, not javascript.
The public facing WCF service is IP-restricted to only allow requests from the public web server
Why don't you just call Ping() when the submit button is pressed and if the service doesn't respond then don't submit the form and show an error.
Something like this in jQuery. This assumses that Ping() returns true if the service is up, false otherwise:
$('#myformid').submit(function() {
var svcUp = Ping();
if(!svcUp)
alert("Sorry, there was an error submitting, please try again.");
return svcUp;
});
Unfortunately any public facing web service that has a low calling cost but high processing cost will be vulnerable to DOS attacks without some type of throttling.
Thankfully WCF has some useful settings for controlling throttling, take a look at MaxConcurrentCalls, MaxConcurrentInstances, and MaxConcurrentSessions
There is really no good solution on the client-side to prevent a DOS attack - I can create a script using your Ping js method that will call it a million times in a loop. You can prevent it on the server side though, by tracking calls per second form the same ip/session/user/otherclient-side identifier. If number of calls per second is over some reasonable limit, you temporarily ban that client.
You can look at http://www.codeproject.com/KB/aspnet/10ASPNetPerformance.aspx - scroll down to "Prevent Denial of Service (DOS) Attack" for an example
Call your function on page load and prior to the submit button. If you have any logging you are using you could insert into a log table for this particular aspx page view and include the IP address of the visitor. Set a threshold and if the IP makes more requests than what you required as proper usage, then put up some type of human-validation item.

Updating the asp.net page from the asynchronous WCF duplex call - object scope - ASP.NET

I've the following doubt. I've a page "MyPage" and i've declared few dictionary objects in the page class.
My doubt is
If i declare the dictionary as a private non-static object i'm not able to use it across the functions in that page class (the object is getting nulled)
But if i declare the dictionary to be static i'm able to across the object across the functions. But will that object be same across all the users who have opened the page right now (guessing that each user will have an instance of the page in turn has an instance for the page class and static variables of a class are invariable across all the instances of the class)
Is my understanding right? How to declare the object to be available across all the functions within the page class and unique for each instance of the page (user).
Update1
Okie, i find that the initialization of the dictionary object in the page class is done in a different thread (WCF Duplex callback). But in the main page thread the dictionary object is still remaining as null (uninitialized). Any ideas?
Update2
Marshalling - useful by any chance?
Update3
In reply to John-
Thanks for your reply. The problem i'm facing now is to pass the data from the WCF callback class at the client side(which will be invoked in a separate thread) to the asp.net page. So how can i do that? View state may help me to persist the data across requests. But when the callback is invoked by the server notifying for a change how should i pass the changes (data) to the UI thread (asp.net page)?
Don't do things like this.
If you need to maintain data between pages, use Session state. That's what it's for. You should remember that you get a new instance of your page class on every request. Do not use statics to keep changing data around for subsequent requests. You will probably get into trouble with multiple requests updating the data at the same time.
You can't do things like this with ASP.NET!
You seem to be treating this as though it were a desktop program - as though your class instance and all state will still be there for you next time you execute a method on the page. That's not true - when the request is complete, your page will be Disposed. Nothing about the page will remain valid.
In particular, if the callback doesn't happen before the request ends, then the callback method had better not reference anything having to do with the request, like your page. That's because the callback might fire after the request is already over! The state is corrupt or worse.
Unless you are going to have the page wait for the callback, you'd really better not use them in your pages. Instead, create a separate Windows Service or something and have it issue the requests and await the callback. The page can then use Ajax or something to ask if the request is complete, and to get the response once complete.
If you think you heard me say to call back to an ASP.NET page, then you misunderstood.
Create a Windows Service. Your Windows Service will host a WCF service that the ASP.NET application will talk to. The WCF Service will keep track of things like who's joined a chat, who's typing, etc.
The web application cannot be notified when something interesting happens. Instead, the web application will have to poll the WCF service, asking if anything interesting has happened. When something happens, the WCF service will pass the "something" back to the ASP.NET application (or possibly, back to the page, called by AJAX).
I misspoke earlier. You simply cannot use a callback contract at all in this situation. It's not like the web pages are like a desktop application, one per user, waiting to be notified. They're more like a desktop application where, when the user makes a request, you take his PC and give him a new one just like it, before the response arrives.
You are right in the second case. In your first case I'm guessing you mean that if a user clicks multiple controls on your page then the event handlers are seeing that the dictionary is null (instead of having the result from the previous event handler).
Remember that every request on a page (even from the same user) creates a new instance of your page class. That means that each time a request starts, your dictionary will be null. The only way for a variable to maintain its value between subsequent requests is to persist it server-side (for example, in user-specific session information on the server) or to push it to the client with the page content so that it can be part of the subsequent request data (so it's stored in ViewState or other storage at the client's browser between requests).
Rereading this question, there are three seperate state machines, and none of them are being coupled together - hence the problem :)
State of the "user state" - these are the key/value pairs in the dictionary, their lifetime spans multiple page requests and callbacks
State of a "page", which needs to consume the data from "user state". Pages are destroyed after each and every page request.
State of the "service call" which needs to populate the data in "user state" Service calls are generally destroyed after each invocation.
There are a few strategies that could enable you to couple the systems:
ViewState such that the state machine for "user state" is sent down as part of the state of the page, and sent back on postbacks. This may constrain how you perform service callbacks
Session such that the state machine for "user state" is stored server side, and can be accessed by key.
Static dictionary of user states, where the key for the outer dictionary would be the identity of the "user state", where the 1st page request would create the "user state" entry, and you'd need to manage teardown. (v.similar to session - though works without ASP.NET).
There are lots of nuances to each solution - I'd advise light reading :)
you are right that a static member will be the same for all instances of the page, and thus all individual users. You need to make it a non-static member if you want to access it from every method in the class. You should look into why the object is null. Are you properly instantiating it at the proper time?

Categories

Resources