SQL Update then Select, Selects the original value - c#

I have a super basic EF method that basically just does:
var obj = context.Set<Objs>().Single(x => x.ID = id);
obj.varBinaryMax = largeByteArray;
await context.SaveChangesAsync();
The method is async Task<...> UpdateObj()
The method calling THAT is an async Task<...>, which has an await when calling UpdateObj().
There are awaits all the way down to a WebAPI Call which is:
public async Task<HttpResponseMessage> UpdateObj(...)
Of course the call to the method chain in the WebAPI is also awaited.
When stepping through the code, everything is definitely slow, because I'm talking about multiple megabytes of Byte[] for this update. That may or may not be the issue.
The UI is using JQuery to make this call:
$.ajax({
type: "POST",
url: 'https://dubs.website.com/api/Object/Edit/' + someID,
data: someImageBytes,
success: function () {
alert('lol, all done');
},
error: function () {
alert('lol, error');
}
});
The problem is... if I refresh the page, which then queries the database for the image bytes, I get back an unaltered old image. Unless I wait about 10 seconds, then refresh, then I get back the updated image.
But, for sure, my update calls all finished, were awaited, and updated the database. So why, for some number of seconds, am I being returned an old object? My WebAPI call to retrieve the object is NOT Caching the original object.
Is SQL server taking a while to update that VarBinary(MAX) field, even after it returns completion?

Related

Two parallel ajax requests to Action methods are queued, why?

I'm developing a video website using ASP.NET MVC.
One functionality I want to have in my application is transocding video. But as the transcoding process could be very time-consuming, I want to show the progress of that process to the client user.
So, my schema is to use one controller action to handle the whole transcoding process and write its progress into a file stored on the server. Meanwhile I use Ajax to call another controller action to read the specified file, retrieve the progress information and send it back to the client for display every 2 seconds during the transcoding process.
To fulfill my plan, I have written the following code:
Server Side:
public class VideoController : Controller
{
//Other action methods
....
//Action method for transcoding a video given by its id
[HttpPost]
public async Task<ActionResult> Transcode(int vid=0)
{
VideoModel VideoModel = new VideoModel();
Video video = VideoModel.GetVideo(vid);
string src = Server.MapPath("~/videos/")+video.Path;
string trg = Server.MapPath("~/videos/") + +video.Id+".mp4";
//The file that stores the progress information
string logPath = Server.MapPath("~/videos/") + "transcode.txt";
string pathHeader=Server.MapPath("../");
if (await VideoModel.ConvertVideo(src.Trim(), trg.Trim(), logPath))
{
return Json(new { result = "" });
}
else
{
return Json(new { result = "Transcoding failed, please try again." });
}
}
//Action method for retrieving the progress value from the specified log file
public ActionResult GetProgress()
{
string logPath = Server.MapPath("~/videos/") + "transcode.txt";
//Retrive the progress from the specified log file.
...
return Json(new { progress = progress });
}
}
Client Side:
var progressTimer = null;
var TranscodeProgress = null;
// The function that requests server for handling the transcoding process
function Transcode(vid) {
// Calls the Transcode action in VideoController
var htmlobj = $.ajax({
url: "/Video/Transcode",
type: "POST",
//dataType: 'JSON',
data: { 'vid': vid },
success: function(data)
{
if(data.result!="")
alert(data.result);
}
else
{
//finalization works
....
}
}
});
//Wait for 1 seconds to start retrieving transcoding progress
progressTimer=setTimeout(function ()
{
//Display progress bar
...
//Set up the procedure of retrieving progress every 2 seconds
TranscodeProgress = setInterval(Transcoding, 2000);
}, 1000);
}
//The function that requests the server for retrieving the progress information every 2 seconds.
function Transcoding()
{
//Calls the GetProgress action in VideoController
$.ajax({
url: "/Video/GetProgress",
type: "POST",
//dataType: 'JSON',
success: function (data)
{
if (data.progress == undefined || data.progress == null)
return;
progressPerc = parseFloat(data.progress);
//Update progress bar
...
}
});
}
Now the Client-side code and the Transcode action method all work fine. The problem is that the GetProgress method will never get called until the Transcode action finishes its whole procedure. So what's wrong with my code? How can I modify it to make those two actions work spontaneously so as to achieve my goal?
Update
Based on Alex's answer, I found that my problem is caused by the session lock mechanism of Asp.Net framework. So disabling the SessionState of my VideoController or setting it as read-only does make the controller responses to the request for retrieving transcoding progress when the action method of transcoding video is being executed. But because I use Session in my VideoController to store some variables for use across multiple requests, this way couldn't be a suitable solution for my problem. Is there a better way to solve it?
You misunderstood the whole point about async/await. It doesn't change the fact that for each single request, there is a single response that is returned. When you call await in your action, nothing is returned to client yet. The only thing it does (in a very high level abstraction) is to release the current thread that handles this request to a thread pool so it could be used for processing other requests. So basically it allows you to use your server resources more efficiently since there are no threads that are wasted waiting for long I/O operations to complete. Once the I/O operation is completed the the execution of the action (that called for await) continued. Only at the end of an action the response is sent to the client.
As for you scenario, if it is a long running task, I would use some kind of background processing solution such as Hangfire and use SignalR to push updates from server.Here is an example
You can also implement something similar on your own (example).
UPDATE:
As #Menahem stated in his comment I maybe misinterpreted part of your question.
Request queuing issue may be caused by incorrect configuration of SessionStateBehavior. Since MvcHandler handler which is used by ASP.NET MVC is marked with IRequiresSessionState interface, only one request at time could be processed per session. In order to change that, make you controller sessionless (or ar least make sure that you are not writing into session in this controller) and mark it with
[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)] attribute.
File creation is blocking call. In other words, until first thread will not close file, second one which makes report will not be able to read contents of that file. As workaround you can create files with percentage of progress. For example movie1-5-percent.txt, movie1-10-percent.txt, movie1-15-percent.txt etc, in order to avoid blocking calls to file system. Then you can check, if for movie1 there is file movie1-15-percent.txt, then you can report to ajax call, that 15 percent of movie was converted. Or choose another non blocking storage. For example you can report result to db in first thread, and read results from db in another.

Sending $ajax via jQuery to C# codebehind not working

I am having unexplained behavior when I post from jquery using ajax to C#.
1) The main page is called not the method I am requesting in jQuery.
To work around this I simply put an if in the page load so that if a particular item is in the querystring it will trigger a series of commands. It does hit that if statement and runs the code perfectly fine. There are some methods that do things like change a color on the map. These never actually happen. I can set a label and it will pass right over it but the label remains unset.
2) strangely enough.... my page has a timer with a refresh on it. It refreshes the page and now the changes are processed.
Here is the way I am calling my method in jQUery:
function mycmethod(param)
{
//alert(precinct);
$.ajax({
url: "myPage.aspx/someMethod",
type: 'POST',
data: "params=" + param,
success: function iGotData(responseJSON) {
// alert("Worked");
},
error: function (xhr, status, errorThrown) {
console.log("Error: " + errorThrown);
console.log("Status: " + status);
console.log(xhr);
alert("Didnt work:" + errorThrown);
},
})
};
It was originally set to async: true but that didn't make a difference.
The method its not calling on load is:
[WebMethod][ScriptMethod]
public Boolean someMethod(string param)
{
setFeatures();
GenerateMap();
return true;
}
I doubt its relevant but I am calling a jquery call with over mouse over of a specific element. That jquery calls a function which calls a asmx web service that returns some jSON. I am calling the mycmethod after the JSON is returned.
Why is my UI elements not responding until the page refreshes. If not, is there a way I can force a refresh like the timer does?
[WebMethods] methods should be declared as static.
I've also found that you might need to specify the content type in your ajax call:
contentType: "application/json; charset=utf-8"
Also, your data option looks suspicious. Maybe you should append it to the url option:
url: "myPage.aspx/someMethod?params" + parm
or, more ideally, send it as either a JSON object or a JSON string:
data: {
params: param
}
or
data: JSON.stringify({
params: param
})
If I understand you correctly, you're loading the page, then calling the server via ajax and expecting the server to change UI elements of the currently loaded page.
It doesn't work like that, unfortunately. Once you've served the page, the server itself cannot manipulate that page without doing a refresh/post back (or something along those lines).
If you want to update the UI without doing a refresh/post back you can have your WebMethod return HTML, and your jQuery success method can update the relevant controls.
Alternatively you could use jQuery's .get() to retrieve a fresh copy of the page via ajax, and update your current page like that. (although it's less efficient)

Is this fire and forget approach correct?

I've implemented instagram api realtime updates. Basically they fire a POST request to a url I provide when there are new images added based on my subscription.
They said:
" you should acknowledge the POST within a 2 second timeout--if you need to do more processing of the received information, you can do so in an asynchronous task."
so I built something like:
[HttpPost]
[ActionName("realtime")]
public async Task<ActionResult> IndexPost()
{
var form = Request.Form;
Request.InputStream.Position = 0;
System.IO.StreamReader str = new System.IO.StreamReader(Request.InputStream);
string sBuf = str.ReadToEnd();
// deserialize this from json
var serializer = new JavaScriptSerializer();
var updates = serializer.Deserialize<IEnumerable<RealtimeUpdate>>(sBuf).ToList();
ProcessNewTaggedImages(updates);
return new ContentResult { Content = "Ok" };
}
where ProcessNewTaggedImages is running async.
public async void ProcessNewTaggedImages(List<RealtimeUpdate> updates)
{
Task.Run(() =>
{
// query Instagram api for new images
}
}
so basically when Instagram POSTs to www.mysite.com/realtime it does not wait for ProcessNewTaggedImages.
I just wanted to make sure this approach is correct for fire and forget approach because under Task.Run I receive a warning saying:
Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the await operator to the result of the call.
but I don't want await here because
the result of my processing does not matter for instagram call
timeout for POST is 2 seconds so I don't want to wait for this processing.
Can you confirm I am on the right track?
Ps: POST is working fine and all works good just wanted to confirm I've not done any mystake because I am mostly beginner to this async approach in C#.
If you need fire and forget functionality you don't need to add async keywords to your methods as your are not doing any awaits. So remove the async keywords from your code and the compiler will not complain about your code.
I think you might need to read though this first.
And I quote: "If an async method doesn’t use an await operator to mark a suspension point, the method executes as a synchronous method does, despite the async modifier."

Simple ajax clock works in everything except for IE for some reason

Here is my simple ajax function:
var callback = function () {
$.ajax({
url: "/Home/Timer",
success: function (response) {
console.log(response); // Fails, but only in IE10
$("#target").html(response);
}
});
}
setInterval(callback, 1000);
and the Controller/Action:
public String Timer()
{
Debug.WriteLine(DateTime.Now.ToString()); // Shows correctly in all browsers
return DateTime.Now.ToString();
}
which works fine in Opera, Chrome, Firefox, but not IE10 for the weirdest reason. In every other browser, the console logs the current time but in IE10, it keeps logging the same time over and over again. I put a breakpoint on my Timer method, and it hits the method correctly, but somehow when it gets back to the success callback it reports the wrong time. Why would that happen?
cache maybe?
try setting cache:false in the ajax options
In safari and some older browsers, (from what I've experienced till now, cache:false doesnt seem to work sometimes). for a more cross browser compatible solution, you could add a data option to the ajax() call and add a random number generator as a parameter. It would be something like this.
var callback = function () {
$.ajax({
url: "/Home/Timer",
//start random number generator
data : { r: Math.random() }
//end random number generator
success: function (response) {
console.log(response); // Fails, but only in IE10
$("#target").html(response);
}
});
}
This way, everytime a server call happens, a new random number will be generated, and since the data is different from the previous requests, ajax requests wont be cached and will ensure a fresh server call every single time.
edit under package and set cache:false in your CSS and call each intermediate function under main class

Update label while a method is running

How do I update a label in a aspx page while a method is running? Perhaps using AJAX (update panel)?
private void button_Click(object sender, EventArgs e)
{
doThings1();
label.Text = "Status1";
doThings2();
label.Text = "Status2";
doThings3();
label.Text = "Done";
}
I want to show step by step. While the method is running when the doThings1() is done, shows "Status1", doThings2() is done, shows "Status2"... In this way, the label doesn't show "Status1" and "Status2", just "Done" when the process is finished. I'd like to show step by step.
This is not an easy thing to do, the way it is in a desktop application. You need to start an asynchronous operation that will continue after the request ends, you'll need to have the client continually poll the server for updates as to the progress, and the server side asynchronous code will need to update some sort of share state (i.e. session, a database, view state, etc.) that the polling method can read the progress from. All around it's quite inefficient (especially if you have a lot of users doing this) and takes some time to write. Here is an example on MSDN that does this, to give you an idea of what's involved.
The rule is: 1 request --> one response.
Different approach:
You can these methods execute with 3 asyncron javascript call and set the labels' text at the success callback.
http://api.jquery.com/jQuery.ajax/
Example:
$.ajax({
type: "POST",
url: "URL.asmx/doThings1",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(result) {
// result will be "done" from the function of webservice below.
// set the first label text
},
error: function(xmlHttpRequest, status, err) {
alert(xmlHttpRequest.statusText + " " + xmlHttpRequest.status + " : " + xmlHttpRequest.responseText);
}
});
Repeat these calls 3 times and do your modifications in different functions.
You can handle your buttonclick at client side with jquery or pure javascript.
You can use a webservice or generic handler to execute server side methods.
How to create webservice
[WebMethod]
public string doThings1()
{
return "done";
}
It sounds like you want to show the progress of some task that is running on the server. The signalr library will allow you to send real time updates to the client from the server. So anytime the task completed a stage (Status1, Status2, etc) of the task, it would send an update to the listening clients with the new status.
You could also have some javascript request the task status from the server every few seconds and display it to the user.

Categories