Redirects with Global.asax file in C# - c#

I have added the following code to my Global.asax file:
<%# Application Language="C#" %>
<script runat="server">
protected void Application_BeginRequest(Object sender, EventArgs e)
{
if (ConfigurationManager.AppSettings["IsReviewServer"] == "Yes")
{
if (!Request.IsSecureConnection)
{
string path = string.Format("https{0}", Request.Url.AbsoluteUri.Substring(4));
Response.Redirect(path);
}
}
}
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
}
etc.....
But my BeginRequest function just gets ignored. How do I redirect my entire application from http: to https:?

If you're using a master page or a base class, I would put your logic there. Global events shouldn't be relied upon for logic like this.
Put the logic in Page_Load (or earlier in the lifecycle) of the master page or base class like this:
protected void Page_Load(object sender, EventArgs e)
{
if (ConfigurationManager.AppSettings["IsReviewServer"] == "Yes")
{
if (!Request.IsSecureConnection)
{
string path = string.Format("https{0}", Request.Url.AbsoluteUri.Substring(4));
Response.Redirect(path);
}
}
}
You could do the above at another point in the lifecycle if you wanted too, like PreLoad or PreRender.
Using global events
If you're going to use a global event, I would actually use Application_EndRequest, because it gets called on every request so the application can clean up resources.

Related

C# how to stop a control's event

I have an .aspx page that has a page_load as follows:
protected void Page_Load(object sender, EventArgs e)
{
if (HttpContext.Current.User.Identity.Name != "")
{
....
}
else
{
FormsAuthentication.RedirectToLoginPage();
return;
}
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
....
}
The issue I am noticing is that when the user clicks the submit button it goes though the Page_Load (goes though the else) and then tries to run though the protected void btnSubmit_Click(object sender, EventArgs e).
Is there a way to make it redirect to the login page and not continue to the next void?
This is NOT an issue. This is the normal ASP.NET Page Life Cycle.
Controls events fire right after the Page_Load event.
Note that the FormsAuthentication.RedirectToLoginPage method does not end the request by calling HttpResponse.End. This means that code that follows the RedirectToLoginPage method call will run.
Assuming you want to stop further processing from within the Page_Load (which I believe is your intention with return):
protected void Page_Load(Object sender, EventArgs e)
{
if (/*I want to kill processing*/)
{
// Method one:
Response.End(); // Though admittedly ugly
// Method two:
this.Context.ApplicationInstance.CompleteRequest();
return; // return as normal (short-circuit)
}
}

Correct way of using variables from global.asax

I have a simple global.asax file that runs some code at startup and stores a handle in a variable. I want to access that variable from my other files in the project. Here is my global.asax:
<%# Application Language="C#" %>
<script runat="server">
static JustTesting justTesting;
static public JustTesting JustTesting { get { return justTesting ; } }
void Application_Start(object sender, EventArgs e)
{
//my code here
}
void Application_End(object sender, EventArgs e)
{
// Code that runs on application shutdown
}
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
}
</script>
And when I want to use that variable...
ASP.global_asax.JustTesting
...which works, but I'm sure there must be a more elegant way of calling it instead of having to add ASP.global_asax. all the time.
You can use Application object.
Reading:
var x = Application["x"];
Writing:
Application.Lock();
Application["x"] = "value";
Application.UnLock();
Reference: http://msdn.microsoft.com/en-us/library/94xkskdf(v=vs.90).aspx
You can also create your own class, which should be thread safe.

Calling pageload after some operation

I have an aspx.cs file with the following code
protected void Page_Load(object sender, EventArgs e)
{
//Some code
}
protected void Removeabc(object sender, EventArgs e)
{
//Some code
}
In the last line of Removeabc i want to reload the page and call Page_Load again. Please help me on how to do the same.
To reload the page, use
Response.Redirect(Request.Url.ToString())
It will call the Page_Load on that reload.
You can use
Response.Redirect(Request.RawUrl);
It will redirect you to the same page and call Page_Load().
You should wrap that logic into a third method which can be called from both handlers:
protected void Page_Load(object sender, EventArgs e)
{
//Some code
DoSomeCleverStuff();
}
protected void Removeabc(object sender, EventArgs e)
{
//Some code
DoSomeCleverStuff();
}
private void DoSomeCleverStuff() {
// Clever stuff
}
It is good practice not to put heavy logic/code into event handlers in C#. Extract the core logic out into either another method or class so that the code can be re-used elsewhere throughout the class/application.
You can redirect to this page using Response.Redirect(Request.Url.ToString()) or if you only want the code in Page_Load to execute you can call Page_Load(null,null)

Global.asax parent application and child application

I'm working on some legacy code right now and I'm trying to move the Global.asax file up to the parent application and it will manage all of the children applications. Currently we have a Global.asax file in all of the children apps (bad).
When I try removing the Global.asax file from the child application, it does not find the parent application's Global.asax file unfortunately. Therefore I cannot stay authenticated within the child app. I was wondering if there is an easy fix to this.
Structure:
parent app
files...
childapp
files..
global.asax
global.asax
I want the childapp to find the parent's Global.asax file.
Thanks guys!
EDIT:
Global.asax
(This is identical in the parent and child apps)
protected void Application_Start(object sender, EventArgs e)
{
}
protected void Session_Start(object sender, EventArgs e)
{
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
}
public void Application_AuthenticateRequest(Object sender, EventArgs e)
{
String cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = Context.Request.Cookies[cookieName];
if (null == authCookie)
{//There is no authentication cookie.
return;
}
FormsAuthenticationTicket authTicket = null;
try
{
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
}
catch (Exception ex)
{
//Write the exception to the Event Log.
return;
}
if (null == authTicket)
{//Cookie failed to decrypt.
return;
}
//When the ticket was created, the UserData property was assigned a
//pipe-delimited string of group names.
String[] groups = authTicket.UserData.Split(new char[] { '|' });
//Create an Identity.
GenericIdentity id = new GenericIdentity(authTicket.Name, "LdapAuthentication");
//This principal flows throughout the request.
GenericPrincipal principal = new GenericPrincipal(id, groups);
Context.User = principal;
}
protected void Application_Error(object sender, EventArgs e)
{
}
protected void Session_End(object sender, EventArgs e)
{
}
protected void Application_End(object sender, EventArgs e)
{
}
As others have stated there is probably a better way to accomplish your goal but strictly speaking, if I understand your question correctly, it should be possible.
The class that each of the Global.asax inherits from must be in a shared assembly. Then you can change the markup for each of the Global.asax files to inherit from that shared class.
<%# Application Inherits="MySharedGlobal" Language="C#" %>
You can remove the code behind for each of the application (both parent and children) but the Glabal.asax file must remain.
You could move the shared code into a base class just as easily that each application object inherits from in the code behind. This would allow you to still add application specific logic as needed.
Now, you could also create an IHttpModule an place the shared code in it and when loaded in the parent application will also be loaded in the child applications (via config inheritance).
Edit:
If am understanding you correctly, you want to run the same code in each application without having it copy and pasted over and over again. If you need to have actual "applications" for each nested site then that code has to run multiple times. That doesn't mean it can't be shared however.
A simple way to do that is to create class that implements IHttpModule and add that to your parent application config file. In the 'Init' method you can hook into the AuthenticateRequest event and run the same code you posted from there instead and remove it from the Global.asax code behind in each child application.
Another way to accomplish it would be to create an implementation of HttpApplication that hooks into the same event (just like it does now). You can then place the shared code in the base class and each class in the Global.asax code behind file would inherit from that. Then you could remove the code from each Global.asax code behind file.
If you create the IHttpModule the Global.asax files could be removed. Otherwise, they would need to stay.

Button click event error

Having just added a new button in my web application, I get an error when clicking on it, and I'm wondering if this is related to misplaced code. I will describe what/where I did, briefly. Thanks very much.
In ascx file:
<asp:Button ID="btn_rezerv" runat="server" Text="Reserve film" OnClick="btn_rezerv_Click"/>
In the ascx.cs file:
namespace CinProj.UserControls
{
public partial class FilmsList : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
PopulateControls();
}
private void PopulateControls()
{
string categId = Request.QueryString["CategID"];
string filmId = Request.QueryString["FilmID"];
....
if (categId != null)
{
.....
}
if (filmId != null)
{
......
Button btn_rezerv = (Button)item.FindControl("btn_rezerv");
}
}
protected void btn_rezerv_Click(object sender, EventArgs e)
{
string fid = Request.QueryString["FilmID"];
ShoppingCartAccess.AddItem(fid);
}
}
}
"Server Error in '/' Application.
Invalid postback or callback argument. Event validation is enabled using in configuration or <%# Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation. "
Another problem could be because your PopulateControls method should probably only be called when during the Page Load when it's not a PostBack. I can't tell from above, but to me it looks like it only needs done on Load. Try wrapping that call with this:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
PopulateControls();
}
}
It's likely the result of making some sort of client change that the server doesn't know about. Many times this is the result of changing values in a dropdown in JavaScript, for example.
To fix, you could:
Do away with using JavaScript for said modification
Use an UpdatePanel and add your control to it. If the client needs to make a change, trigger the UpdatePanel's update in order for the control's viewstate to update.

Categories