Controller Post - Duplicate Records - Mozilla Firefox - c#

I am providing a link via Mail to the Users. When they click on link Page Opens & as they hit Submit button, Controller Post Method runs.
saveRecords()
{
-- business logic
-- code validation for checking duplicates
-- saving records
}
All was working well. But suddenly it was found that duplicate records are being entered. There is no problem in Code logic.
After tracing it was found that it is happening when browser is Mozilla. And scenario is User clicks on Mail link twice so 2 tabs open & if he hits Submit button on each tab then Duplicates are being inserted.
Note - if same Page we hit submit it validates properly.
Problem occurs when 2 tabs are open & Submit button is clicked in both tabs & Browser is Firefox.
Can you suggest me a solution?
This is summary of Code :-
var obj = ctx.tblDuty.FirstOrDefault(m => m.Id == recordId);
if (obj.EntryStatus == Status.Approved)
msg = "Duty already Approved.!";
else if (obj.EntryStatus == Status.Rejected)
msg = "Duty already Rejected.!";
var data = service.saveDuty(model, userRole);

Why don't you introduce a lock around the method (if you can't figure out why Mozilla sends two POST calls) and wrap the code in there:
static object _lock = new object();
saveRecords()
{
lock(_lock)
{
-- business logic
-- code validation for checking duplicates
-- saving records
}
}
EDIT 1 [Blocking Collection with working rows]:
This is not the best solution, but it will get it done for you. Maybe consider using Monitor if you wanna do it in a better\more optimal way.

Related

How pass a values from a web form to another in ASP.NET?

I am trying to send string data from one web form to another, however it throws the System.NullReferenceException error. I read in the Postgress documentation that this error means there is no data to work with. This is the code for the first form:
protected void Button2_Click(object sender, EventArgs e)
{
editar ed = new editar(tname.Text.ToString());
//ed.putId(tname.Text.ToString());
String url = "editar.aspx";
Response.Redirect(url);
}
Creating the object of the second form was one of the ways I found to send the data, but it keeps throwing the error. In the second form you should receive it.
public editar(string name)
{
this.tname.Text = name;
}
The basic idea is that the string is received in the second form to put it in a text box and there, by means of a button, the information of a database can be updated.
protected void Button2_Click(object sender, EventArgs e)
{
upt = new NpgsqlCommand("update usuario set cedula = '" + tcedula.Text.ToString() + "' where nombre = '" + tname.Text.ToString() + "'", conn);
upt.ExecuteNonQuery();
}
I have already tried through the POST and Session method, the problem with these two methods is that although the data arrives correctly every time the page is reloaded the data is reloaded and that happens each time the button, therefore the SQL statement to update the information is null, that is, it executes it, but it does not update the database. I use Visual Studio 2019, ASP.NET, and Postgres.
There are two things to understand here:
Web Forms still use HTTP requests for each page view and even for each server event like button clicks.
Form class instances do not persist between requests. Your
code runs for long enough to send some html or javascript to the
browser, and then everything is immediately thrown away; nothing
stays in memory. Even if the same user requests the same page again
(ie, clicks refresh in their browser), you still get an entirely new
instance of your page class that doesn't know anything of what has come before.
Therefore, if you have a value you want to use across HTTP requests, as in this case when you have two different forms, you have to put it somewhere that will be available when the later http request is processed. You can do that several ways: the session, a GET (url) or POST parameter, or save to a database during the first request and receive on the second.
In this case, a session value seems most appropriate, but it's hard to be sure without knowing more of what you're doing.
And for God's sake, fix that glaring SQL injection issue. You shouldn't be writing database code for the web without knowing about that.

object reference not set to an instance of an object, when using session variable in MVC4

NOTE
it is not duplicate question I am asking, I have read 3 different links from stack as showed below, but none of them shows resolution for my question (or) reason, so please let me know what i am doing wrong
link1
link2
link 3
I developed MVC application, where username from login page taken to controller to pull the data, where it loads up the value of that username, so I want that Username to be exist until i quit my application, so what I did was did some R&D what to use to store and save the data and pass it to another page,
first I used "TempData" which works fine to my scenario , where it pulls the data as I needed, but the error occurs when application is idle for 5 min then, if i press the Refresh button or F5, I get the above error, username is null generating error message "object reference not set to instance of an object" I know why this error generates.
later I searched it again, used session variable to store and send it, even it does works fine same as tempdata but after few mins like 5 mins and more, if page refreshes generates same message, I believe the syntax used in tempdata and session are correct since it works fine, I am posting code of the way I am using it in MVC, please let me know any mistakes I have done, or let me know what should I do to fix this problem, which should work for longer duration of idle, unless I use session time to quit the application.
NOTE
I have not used any session time, like if application is idle for 5 mins it should quit the application.
CODE
public ActionResult ValidateLogIn(FormCollection postedFormData)
{
LoginViewModel.LoginDataModel.UserName = Convert.ToString(postedFormData["UserName"]);
LoginViewModel.LoginDataModel.Password = Convert.ToString(postedFormData["Password"]);
// ViewBag.Message = LoginViewModel.LoginDataModel.UserName;
// TempData["UsrName"] = LoginViewModel.LoginDataModel.UserName;
TempData.Keep();
Session["UsrName"] = LoginViewModel.LoginDataModel.UserName;
// with some code..........
}
public ActionResult LandingPage()
{
//////ViewData["message"] = TempData["UsrName"].ToString();
Session["message"] = Session["UsrName"].ToString();
ViewData["person"] = Convert.ToInt32(TempData["UserTypeID"]);
TempData.Keep();
String PatID = Convert.ToString(Session["message"].ToString());
int PersonType = Convert.ToInt32(ViewData["person"]);
PatientDetailsViewModel = PatientDetailsDataAccessService.LogInEnquiry(PatID);
return View("../PatientDetails/PatientDetailsView", PatientDetailsViewModel.ServiceList.AsEnumerable());
}
and this is the error which generates when refreshed
You can use User.Identity.Name once the user has logged to get the user name. This way you dont have to mess about with temp data, viewbag or viewdata.

Automated system for opening other website links in new window/tab

I have a website, in which when user clicks a link it opens up in the same window if it is of my website's page, else in new window if domain is different. But I am doing this manually like this:
Open Link
checkdomain() checks the domain name of the link and returns true if it's of my website else false. I used the code from [ HERE ] for this purpose.
My question is: Is there any efficient and client side way available for checking link domains and open up them in new windows/tab if of another website(domain)? Like a JavaScript solution will be better, but then again JavaScript can be disabled by user. So, is there any other solution? Even JS solution will be great. Ignoring the disabling by user.
Somewhere on the page, or in an external JS file:
function externalLinks() {
if (!document.getElementsByTagName) return;
var anchors = document.getElementsByTagName("a");
for (var i = 0; i < anchors.length; i++) {
var anchor = anchors[i];
if (anchor.getAttribute("href")
&& anchor.getAttribute("rel")
&& anchor.getAttribute("rel").indexOf("external") >= 0)
anchor.target = "_blank";
}
}
window.onload = function() {
externalLinks();
};
Then, any external links just need to have rel="external" in the markup. For example:
Click here!
The main advantages of this approach is that you're not going to cause any validation errors, even with an XHTML Strict doctype. Users are also able to easily prevent links opening in new windows by simply disabling JS.
If you need the decision of external/internal to be made automatically (and client-side), you can alter the logic of externalLinks to base the decision on the href attribute rather than the rel attribute. Of course, if you've already got the external/internal logic functioning in your codebehind, I would recommend using that information to render the anchor with the appropriate semantics (with rel), rather than re-writing almost identical code in your client-side JS.
Try comparing your link url's host part (www.wrangle.in) with following in you function logic.
string currentURL = HttpContext.Current.Request.Url.Host;
I do not recommend to compare the name (i.e http or https), you can split using substring function.
For Client side
var homeURL = document.location.hostname;
$('a').each(function() {
if ( $(this+'[href*='+homeURL+']')) {
$(this).attr('target','_self');
}else{
$(this).attr('target','_blank');
} });
This link may help you to understand Url Parts.

How can I create a 'pause' inside a loop in a web application so I don't 'hammer' an external service?

I have a basic search which gives a list of results of html documents. You can click on those results and go to a page "view.aspx?id=xxxx" to see those html documents.
A feature on the results page is to "Compile all results into a PDF", essentially downloading the HTML of the "view.aspx?id=xxxx" page for every result in the search into a PDF.
Thus I have a loop (for simplicity sake I've hardcoded a loop with the id's):
Document doc = pdfConverter.GetPdfDocumentObjectFromHtmlString(
getHtml("{...}View/Default.aspx?id=16480")
);
int id = 16481;
while (id <= 16972)
{
doc.AppendDocument(
pdfConverter.GetPdfDocumentObjectFromHtmlString(
getHtml("{...}View/Default.aspx?id=" + id)
)
);
id++;
Thread.Sleep(250);
}
How do I properly take a break between each request? If I do not break the webserver thinks I'm hammering it and kills my session etc. I've seen TONS of Stack overflow posts about not using Thread.Sleep in a web page code-behind, but can't seem to find any of those posts where an alternative is given.
(Note that this is an internal authenticated site, and if you are logged in, you have access to all the ID's, the ID's are a combination of data, not the primary key, thus I don't believe I must worry about the obvious direct object reference)

Facebook "fan gate" with C#/asp.net

The problem is that 1) Facebook seems so fluid with how it allows developers to interact with it (FBML, iFrame, different versions of SDKs) and 2) Everything I find is either PHP or Javascript and I have NO experience with those. What I am trying to do seems sooo simple, and I can't believe there isn't an easy way to do this.
What I have:
I used Visual Studio 2010 to create a simple web application (asp.net/C#) that asks the user for some info (first name, last name, email, etc.). I have a button on there called "Submit" that, when clicked, saves the entered data into a database. I have this hosted on GoDaddy (I know, I know...heh) and it works just fine. No problem here.
I created a "Facebook App" that uses the iFrame thingy so that basically I have a new tab on Facebook that displays my web app mentioned above. This works fine too. The tab is there, the web app is there, and users can enter the data and it is saved to the database. No problem here.
What I WANT:
I want the web app (the thing displayed by the facebook app) to only show the data entry part if the user currently "likes" the facebook entity. I DO NOT want to have to ask permission. I just want to know if they are a fan of the company's facebook "page" that has this app. So I need two things here, shown in my pseudo code below:
Part 1 (check if user is already a fan):
If (user is fan)
{
Show data entry area (unhide it)
}
else
{
Show "Click the like button to see more options"
}
Part 2 (listen for "like" event)
WhenLikeButtonPressed()
{
Show data entry area (unhide it)
}
I've seen stuff about "visible to connection", C# sdk, edge.create, etc. but I just can't make heads or tails of it. I don't mind putting in Javascript or PHP if someone could please give me exact, "Fan Gate for Dummies" steps. Please, I'm going crazy over here :-(
The key is is the signed_request that Facebook posts to your app when the user accesses the page. It contains the data on whether or not the user likes the page. You shouldn't need to worry about catching edge events on an actual tab FB page as it get's reloaded when the user likes/unlikes the page.
You'll need to decode the signed request with your app secret to get the like info. There are examples provided for PHP but I'm sure with a little google help you can find decode info for the signed_request for asp.net/c#.
Here's the php decode for reference:
function parse_signed_request($signed_request, $secret) {
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
// decode the data
$sig = base64_url_decode($encoded_sig);
$data = json_decode(base64_url_decode($payload), true);
if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') {
error_log('Unknown algorithm. Expected HMAC-SHA256');
return null;
}
// check sig
$expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
if ($sig !== $expected_sig) {
error_log('Bad Signed JSON signature!');
return null;
}
return $data;
}
function base64_url_decode($input) {
return base64_decode(strtr($input, '-_', '+/'));
}
and the link https://developers.facebook.com/docs/authentication/signed_request/ the like info will be contained in the page variable

Categories

Resources