JavaScript PageMethods call loosing HttpContext.Current State - c#

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

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.

What causes if/else expressions to be re-evaluated?

Working off the Blazor hosted template, in my MainLayout.cshtml, I have something like:
#inject UserInfo userInfo
#if(userInfo.Name == "bob")
{
<div class="login-panel">
<p>Hi Bob!</p>
</div>
}
else
{
<LoginPanel />
}
and then in a separate Login.cshtml:
#inject UserInfo userInfo
async void Login()
{
userInfo.Name = "bob";
}
But logging in doesn't cause a change to the 'login-panel' in MainLayout.cshtml. I was able to get this to work if everything is in a single file and I am only checking for whether a particular variable is null or not (see here), so I assume the Blazor framework has specific criteria which illicit a page to re-evaluate such blocks. Is this accurate? If so, what is the best way to force this re-evaluation?
Edit: I played around with it a bit more, eventually discovered the StateHasChanged protected member function, which I assume is called after Init has completed, hence why the previous example works. I think a working solution is to have my UserInfo object implement INotifyPropertyChanged, and then register a change handler inside MainLayout.cshtml to call StateHasChanged() for views that need to update when login status changes.
Yes. Blazor uses something called StateHasChanged just like INotifyPropertyChanged.
However the difference is, in XAML frameworks the XAML will only update those properties which has called INotifyPropertyChanged, but in Razor when StateHasChanged is called the UI framework will refresh the whole UI tree of the component (at least as of now) the element is residing.
Then who has called the StateHasChanged if its not done by you. When an element gets an input (You are clicking a button) the blazor will automatically set the StateHasChanged under the hood.
More reads"
https://github.com/aspnet/Blazor/issues/409
https://learn-blazor.com/pages/data-binding/
https://github.com/aspnet/Blazor/issues/359
https://github.com/aspnet/Blazor/issues/407

MVC razor refreshing view after timeout

I have come across an issue with my mvc razor website where it doesn't refresh properly my page after hitting a timeout.
Here's how I process the whole thing:
My application allows to go through multiple steps. Each step reloads the same view (index.cshtml), the difference being in the session variables. The session variables are used as parameters to make ajax calls to a webservice to get the content to be displayed within the page.
The user can select items displayed within the page and go to the next step. When they click next, it triggers a post (ajax to controller) that will add these items into a session variable so that the selection stays throughout the process and that the user can see all the items selected in the previous steps as he progresses.
I don't want the application to crash when accessing methods (like next, previous, save, etc.) because the session variables have expired.
The way I figured I would prevent that is by decorating my methods in the controller with an attribute that checks if a session variable (isActive) is set, and if it is not, I add a RedirectResult to my filterContext.
public class SessionExpireAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if(filterContext.ActionDescriptor.GetCustomAttributes(typeof(SkipSessionExpireAttribute), false).Any()){
return;
}
if (HttpContext.Current.Session["isActive"] == null)
{
HttpContext.Current.Session["timedOut"] = "true";
filterContext.Result = new RedirectResult("~/Session-Expired", true);
return;
}
}
}
I have set in my routes a route for this url so that it "triggers" the Index method of the controller. (which is the method that returns the view). That way, all session variables would reset, the URL is changed to "Session-Expired" and the page is reload (sending back to the first, default, step).
I tested and it does "trigger" the Index method and goes through it as intended and the Index method returns the view. The problem is, my page never gets reloaded.
Index method is:
[SkipSessionExpire]
[Themed]
public ActionResult Index()
{
// Some code.
return View();
}
So I thought maybe it would be related to caching. I tried several methods found on this wonderful website such as adding:
[OutputCache(Location = System.Web.UI.OutputCacheLocation.None)]
with no real success.
I also tried some "hack" by redirecting to another action which would load a new page (test.cshtml) instead and this page would then redirect to the original view (index.cshtml). The test page worked when I tryed calling it with URL but for some reason, it still won't load the page when redirecting to the action.
My "Next" method (which doesn't get called because it is skipped because of the attribute, which is intended):
[HttpPost]
[Themed]
public JsonResult Next(object item)
{
//Some code.
return Json((string)Session["CurrentUrl"]);
}
The attribute [SessionExpire] is applied to the Controller (so every method within the controller gets it).
I just now tried to put a timeout on the ajax call made to the controller (from the view) in hopes that after tha ajax calls timeouts, it could just redirect to the Index page. It doesn't work (nothing happens on first click on the "next button", and second click bring me one step too far because it is like I went back to first page and then clicked next once).
Also, if I simply refresh the page after the timeout (manually). It realoads the first page with all session variables cleared (which is what I want to do programmatically).
To sum it, up. I would like to know if anyone has experienced something similar or if someone can guide me towards a solution so that I can get a way to refresh the page so that it's sent back to the first (default) step. Also, if I misunderstood something, feel free to tell me! I'm still learning so I'm more than glad to hear constructive feedbacks to help me understand how all of this works.
If you feel I'm too vague or you simply need additional details to help me solve this, just let me know and I'll add whatever is needed. I did quite a bit of research but I might have missed something so if you find something that could be useful, make sure to share.
Thanks!

C# Fire Webbrowser inside a method

I'm trying to write a code in C# which implements Brute-Force Attack to my temporary webpage in order to try crack the login system.
Something like this:
private void buttonHack_Click(object sender, EventArgs e)
{
while (!found)
{
textBox_pw.Text = guess;
guesser.NextGuess();
webBrowser1.Document.GetElementById("user_id").SetAttribute("value", textBox_ID.Text);
webBrowser1.Document.GetElementById("password").SetAttribute("value", textBox_pw.Text);
webBrowser1.Navigate("javascript:enter();");
guess = new String(guesser.CurrentGuess);
}
}
// 'guess' and 'guesser' are for the BF Attack.
But apparently WebBrowser doesn't 'fire' until the method that it's called inside of returns. I have tried to put the part inside the while loop into the Webbrowser_DocumentCompleted event, so that it would literally loop (as when the page load is completed then do the same again and again...) But this way had its issues, like if the page document gets completed fast then it skips the rest of the code and goes to the top of DocumentCompleted method, and as the result weirdness!!!
So any neat ideas how to fix it?
Generally, Brute-Force attacks are not done by manipulating the web page itself, but rather by generating traffic to the server that does the credential validation (unless of course you are validating on the client in which case a simple javascript code review will suffice).
Code is written that mimics the webbroser control's interaction with the server (in order to tap into SSL-protected traffic).
You can not do a loop like this because .Navigate is an async method. You need to subscribe to the DocumentCompleted event on the brwoser control and do your work there.
Also, I'm unsure wheter .Navigate will take a javascipt: location.

"Callback Error: Invalid response from server" from C# ASP.Net application

I have an ASP.Net application with a button containing the following Javascript to be invoked when it is clicked:-
function calculate() {
sectionIndex = getSelectedRadioIndex("section");
compositionIndex = getSelectedRadioIndex("composition");
CallBackOU.callback( "calculate" , sectionIndex, compositionIndex );
}
I can verify that control reaches the last line of this function by setting a breakpoint on it. But instead of invoking the method in the code-behind file...
protected void CallBackOU_Callback (object sender, ComponentArt.Web.UI.CallBackEventArgs e)
{
//blah blah
}
I get a dialogue reporting
Callback Error: Invalid response from server.
This dialogue appears three times, after which the page sits there doing nothing (forever, so far as I can make out).
I can't find any information about this. Can anyone give me any clues or pointers about how to go about diagnosing the problem?
Without seeing the signature of the calculate callback method this is only a shot in the dark but some issues i have encounter when invoking web methods from javascript are make sure the method is properly decorated [WebMethod], make sure the method is static, make sure the parameters are of the correct type and named properly (they are infact case sensitive when deserializing JSON iirc). A little more information regarding how the call is made (JSON/XML) and the signature might help. Also, you can try using fiddler to see if you get any more information regarding the error.

Categories

Resources