pass variable from page load to button click event - c#

i am creating a page that when page load it will connect to the database to check the user status to determine which part can be shown, then user can click submit button which need to connect to the database again to update some information.
So is there a efficient way to do this? now I have to connect to the database twice or is there a method to pass variables from page load event to button click event.
Any idea? thanks

I hope I understood your question correctly. All you need to do is extract all functionality which is aware of connecting to a database and then verify permissions in a separate method. Basically, a simple Extract Method technique.
public void Page_Load(...)
{
// check whilst first loading of the page
// if you need checking each time as page loading - remove if() below
if (!IsPostBack)
{
YourConnectToDatabaseMethod(defaultParams);
}
}
public void OnButtonClick(...)
{
var params = ... grab required params;
YourConnectToDatabaseMethod(params);
}
private void YourConnectToDatabaseMethod(TypeOfParams params)
{
}

Your database connection most likely comes from a connection pool so even if you call Open, you are not actually reopening a connection but using an already opened one.

Related

Selenium - how to verify form not submitted on click? (client validation works)

Is there a way to verify that the page is not reloaded when click "Submit" using Selenium?
Currently the test instructs the browser to open a submit form and immediately clicks "Submit" without filling the fields.
In that way I will verify that the client side validation works and doesn't make unnecessary requests to server.
I'm using C# by the way - if it matters.
I think in this case you would have to verify the page upon submission, either the successful page or original, to determine if the form input was successful :)
Normally you would verify the error message returned on the given pop-up or sign-in form, which would lead you to conclude that the input was unsuccessful, but in this case, that doesn't seem to be possible.
Asserting the given page URI and/or page elements, will help you determine the outcome.
If only a reload check is needed, you can check for staleness of an element that was present on the page earlier. A small code example:
public bool IsNewPageLoaded(IWebElement elementToGoStale)
{
try
{
var enabled = elementToGoStale.Enabled;
return false;
}
catch(Exception ex)
{
if (ex is StaleElementReferenceException || ex is NoSuchElementException)
{
return true; // Expected exception on accessing stale element: page has been renewed
}
throw ex;
}
}
The nice thing is that you don't need any extra information about what happens after a page load: all you need is to store an IWebElement on which you can check later on.
I use similar checks in my tests. Although I still consider the try/catch part ugly, so far it has proven to be extremely reliable.
based on #Tybs 's answer, I've managed a helper class.
public class NoReloadVerificationContext : IDisposable
{
private readonly IWebElement bodyElement;
public NoReloadVerificationContext(IWebDriver webDriver)
{
this.bodyElement = webDriver.FindElement(By.TagName("body"));
}
public void Dispose() => Assert.True(this.bodyElement.Enabled);
}
I've seen such approach in some software projectes that provides API - for example creating a context that can make operation without be signed as admin until it's disposed.
An example usage:
// This block asserts that no reload occurred after executing operation inside
// Else it throws an exception - which is OK for me.
using (new NoReloadVerificationContext(driver))
{
// this will submit the form and cause page reload because of missing client vlidations
driver.FindElementByCssSelector("form input[type=submit]").Click();
} // The exception will occur here.
I don't know whether this is the best solution, but it will work in most cases (not only in forms)
The other approach was to get the value of __RequestVerificationToken inside my form (MVC generates it at the end of each form), then perform some actions, after that get the value again and compare with the old one. But this will work only for form submits.

DevExpress XAF - Test if an object is registred before executing code in ViewController

I'm developing using DevExpress XAF, my problem is a little bit tricky, in short, when I save my class I make changes in other classes based on the data provided, I realized this with a controller that executes code when I close the detail view, the problem is that there is a scenario that does not meet my needs, here is it:
When I open a detail view already existing and that I modify some data, when I close the window, the program displays a window of confirmation ("do you want to register?) when I click on no, normally my view controller will not do anything because I refused to change my class data
Finally here is my question: How to test in my view controller if the object was registered or not before proceeding to the change and execute my code?
When you say register, I think you mean save.
You can use the ObjectSpace.GetObjectsToSave() method to obtain a list of objects which will be saved when ObjectSpace.CommitChanges() is called. You can then determine whether View.CurrentObject is in this list.
Alternatively you could use the ObjectSpace_ObjectChanged event. Something like this.
public class MyViewController : ObjectViewController<DetailView, Contact> {
protected override void OnActivated() {
base.OnActivated();
ObjectSpace.ObjectChanged += ObjectSpace_ObjectChanged;
}
void ObjectSpace_ObjectChanged(object sender, ObjectChangedEventArgs e) {
if (e.Object == View.CurrentObject) {
// execute your business logic
}
}
protected override void OnDeactivated() {
base.OnDeactivated();
ObjectSpace.ObjectChanged -= ObjectSpace_ObjectChanged;
}
}
See here for a Support Center discussion of a similar request.

ASP.NET session drop event

Is theire a way, to get noticed if an asp.net web forms session is droped (For example, the client cloeses the browser = timeout)?
We have one session for the temporary user shopping card:
HttpContext.Current.Session["UserShoppingCard"] = new UserShoppingCard();
Every thing works fine, besides the functions explanied above.
Thank you!
I would try to intercept the Session_End event in the global.asax file and put some logging in there, it might not happen right when the browser is closed but it will happen at some point anyway once the session is terminated and you can include your logic in there.
In fact the server never knows when a browser is closed or if instead a connection issue is making the client unable to connect.
As said before, complementing with code...
public class Global : System.Web.HttpApplication
{
protected void Session_End(object sender, EventArgs e)
{
//Do your things here when session ends...
}
}

Refresh page repeat database transaction?

I have over 30 aspx pages, i have discovered a problem recently that if i did any kind of database transaction like insert, update, delete and then after the transaction is complete i pressed F5 or refreshed the page in anyway the same is transaction occur.
I searched for a solution but all i could found is that i have to check for viewstate on each button which is impossible, cause that means there will be a lot of work. There got to be generic solution, please help me in this problem.
Edit:
Here is the code on one of the buttons which change a value in data base to either true or false:
protected void btn_Publish_Click(object sender, EventArgs e)
{
if (Convert.ToBoolean(int.Parse(hf_Published.Value.ToString())))
{
publish(false);
}
else
{
publish(true);
}
}
After the execution of the code if refreshed the page the same code is executed, i noticed that since a break point was placed on this method.
You can try this. I used this in several project and working successfully.
public bool IsRefreshed
{
get
{
if (Convert.ToString(Session["RefreshTimeStamp"]) == Convert.ToString(ViewState["RefreshTimeStamp"]))
{
Session["RefreshTimeStamp"] = HttpContext.Current.Server.UrlDecode(System.DateTime.Now.ToString());
return false;
}
else
{
return true;
}
}
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
ViewState["RefreshTimeStamp"] = Session["RefreshTimeStamp"];
}
protected override void OnLoad(EventArgs e)
{
if (!Page.IsPostBack)
{
Session["RefreshTimeStamp"] = HttpContext.Current.Server.UrlDecode(System.DateTime.Now.ToString());
}
base.OnLoad(e);
}
There IS a generic solution, used for years by thousands of developers.
And the solution is: each time you perform an intrusive process at the server (insert/update/delete) you don't just render the page but rather you redirect the response with 302 to a fresh page with "your transaction succeeded" message.
This way, pressing the F5 will just refresh this message page, not the original page which triggers the transaction.
It is up to you whether or not this is directly applicable in your scenario.
http://en.wikipedia.org/wiki/Post/Redirect/Get
To fix this issue you could check the following:
Disable the submit button when necessary
Add some validation to your code and check for double entries
Redirect the user to another page after submit
Unless it's a real 'transaction' like payments etc. (which others already explained, do redirect etc.),
You could also try defining caching on your pages that interact with the Db or are bottlenecks for your app.
If you wanna have always live info (and it's that 'alive' type of app) then no luck with that solution (but even then), but usually, you can put some reasonable time expiration on how 'fresh' you want your data to be.
Caching ASP.NET Pages

JavaScript PageMethods call loosing HttpContext.Current State

I am in a bit tricky situation. I am using JavaScript's PageMethod functionality where I am invoking a PageMethod which works like a gem. However I am having an issue in accessing the HttpContext's state which returns me a value "SYSTEM" for
HttpContext.Current.User.Identity.Name
which is not the actual current User Name.
I know there are couple options like storing HttpContext.Current in a Session or saving Context's state in some other custom container but given a web farm environment I am assuming that this will not work as expected.
Here is the code I am working on with
function MyFunction(){
PageMethod.MyPageMethod();
}
here is the signature of the server method
[System.Web.Services.WebMethod()]
public static void MyPageMethod()
{
// gives me "SYSTEM"
var user = HttpContext.Current.User.Identity.Name;
}
Also if I use the above code to access user name in OnLoad event of the page then it works fine and returns me the CurrentUserName.
I am trying to get the above code to work in an ASP.NET Webform... :)
So I am wondering if there is a way to access the current actual user in page methods without making use of sessions.
Any help will be deeply appreciated.
NiK...
After quite some reading I think I was trying to do something which is not correct as to how page methods work. It gets quite tricky when your application's authentication system is windows based and these page methods when you invoke from JavaScript will not cause a postback and do not invoke the HttpModules. Instead it just calls that page method.
FYI, we had our own custom HTTPModule to handle security.This is even before any other HttpModule occurs and this was not being invoked while calling the page method as we are not doing a postback or even a partial postback (so the whole "niche" of a HTTPPost was missing). Moreover this led to a conclusion that we were making service calls without any authentication and was potentially a big security issue for us.
The bottom line is it was a bad design, well having said that I would like to mention about the solution/workaround we came up with and here is what we did. So, the only option we had is to do a postback keeping the UI alive and we wanted to update a label's message asynchronously and we achieved it by doing a hack using Sys.Application.add_init.
<script language="javascript" type="text/javascript" >
Sys.Application.add_init(function() {
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequest);
});
function beginProcess() {
processCurrentItem();
}
var currentItem = 0;
function processCurrentItem() {
if (currentItem < 5) {
currentItem = currentItem + 1;
__doPostBack('updatePanel', currentItem);
}
}
function endRequest() {
processCurrentItem();
}
</script>
The markup we had in place was pretty simple with a label in the update panel and a button that invokes the "beginProcess()" function. Finally in the OnLoad we had the following code in place
protected override void OnLoad(EventArgs e)
{
if (this.IsPostBack)
{
this.lblLabel.Text = "text you may wanna update with";
// Call the Method you may wanna call
// also you may use Request["__EVENTARGUMENT"] to know who caused the
// postback and Request["__EVENTTARGET"] to access the argument you may
// have passed in.
}
}
And this solution is no longer using the JavaScript Page methods. And based on this solution if anyone thinks I am missing something here or think there is any other other way of doing this then do update this post with your suggestions.
NiK

Categories

Resources