Redirect to ASPX file from .cs File - asp.net

In asp.net Website, On a WebForm, after button onclick event I am calling code behind method as below
protected void Button1_Click(object sender, EventArgs e)
{
MyClass obj = new MyClass();
String res = obj.CallMe("some parameters");
}
Where MyClass resides in MyClass.cs file.
Inside CallMe() :
public String CallMe("some parameters")
{
String to_return ="";
//some code : to_return="something";
string page_name= // some code returns a name of page to redirect to
if(page_name is null)
{ return to_return; }
else
//redirect to page_name;
}
How to redirect from .cs file since we dont have access to HttpResponse object?

If your class is being called from within a web page, you have access to the static HttpContext.Current instance in the class. Just import the System.Web namespace and call as normal:
using System.Web;
System.Diagnostics.Debug.WriteLine(HttpContext.Current.Timestamp.ToString());
HttpContext.Current.Response.Redirect("http://www.google.com");

try this
if(HttpContext.Current != null)
HttpContext.Current.Response.Redirect("~");
Using the HttpContext you can get the current request, response etc. However be careful to always check to ensure the current context is not null, especially if you are calling from your business layer classes.
ASP.Net Forum

Related

Is there any built in Events in asp.net which triggers for all PageLoads?

After Completing My asp Project I came up with a new requirement. For this, I have to Execute some code in all page Load events. Can I get an event for all those page loads? I can't use Session_start of Global.asax since it will include WebHandlers with Session State. Any Ideas?
You keep a Base Page and Inherit it from all aspx pages. In this way you can keep the logic centralized.
Example
Aspx Page
public partial class MyAspxPage : BasePage
{
}
Base Page
public class BasePage : Page
{
protected override void OnLoad(EventArgs e)
{
}
}
You should also leave AutoEventWireup set to false.
Session start would not be suitable as it will only be fired when a users is given a new session rather than each time a page is loaded.
There are several options, including using a base page which all of you pages inherit from. This will mean you need to remember to hook this up to all pages.
My suggestion would be to write an http module which is fired for all aspx page loads.
You will need to create a module which implements System.Web.IHttpModule.
using System;
using System.Web;
public class HelloWorldModule : IHttpModule
{
public HelloWorldModule()
{
}
public String ModuleName
{
get { return "HelloWorldModule"; }
}
// In the Init function, register for HttpApplication
// events by adding your handlers.
public void Init(HttpApplication application)
{
application.BeginRequest +=
(new EventHandler(this.Application_BeginRequest));
application.EndRequest +=
(new EventHandler(this.Application_EndRequest));
}
private void Application_BeginRequest(Object source,
EventArgs e)
{
// Create HttpApplication and HttpContext objects to access
// request and response properties.
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
string filePath = context.Request.FilePath;
string fileExtension =
VirtualPathUtility.GetExtension(filePath);
if (fileExtension.Equals(".aspx"))
{
context.Response.Write("<h1><font color=red>" +
"HelloWorldModule: Beginning of Request" +
"</font></h1><hr>");
}
}
public void Dispose() { }
}
Then hook it up in the web.config as per the example here.
<httpModules>
<add name="HelloWorldModule" type="HelloWorldModule" />
</httpModules>
You would need to check the context.Request.Path property in the module to exclude any request where the path did't meet your criteria (i.e. not ending aspx).
More info here.
https://web.archive.org/web/20200618051219/http://www.4guysfromrolla.com:80/demos/printPage.aspx?path=/articles/011404-1.aspx
I think the best solution here whould be to create a custom base page class which implements PageLoad and then inherit all your pages from it.
Something like:
public abstract class BasePage: Page
{
protected void Page_Load(object sender, EventArgs e) {
// your code
}
}
You can register base page class in web.config:
<system.web>
<!-- ... -->
<pages pageBaseType="MyWeb.UI.BasePage" />
<!-- ... -->
</system.web>

Call the default asp.net HttpHandler from a custom handler

I'm adding ASP.NET routing to an older webforms app. I'm using a custom HttpHandler to process everything. In some situations I would like to map a particular path back to an aspx file, so I need to just pass control back to the default HttpHandler for asp.net.
The closest I've gotten is this
public void ProcessRequest(HttpContext context) {
// .. when we decide to pass it on
var handler = new System.Web.UI.Page();
handler.ProcessRequest(context);
MemoryStream steam = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
HtmlTextWriter htmlWriter = new HtmlTextWriter(writer);
handler.RenderControl(htmlWriter);
// write headers, etc. & send stream to Response
}
It doesn't do anything, there's nothing output to the stream. MS's documentation for System.Web.UI.Page (as an IHttpHandler) say something to the effect of "do not call the ProcessRequest method. It's for internal use."
From looking around it seems like you can do this with MVC, e.g. : MvcHttpHandler doesn't seem to implement IHttpHandler
There is also this thing System.Web.UI.PageHandlerFactory which appears that it would just produce a Page handler for an aspx file, but it's internal and I can't use it directly.
This page: http://msdn.microsoft.com/en-us/library/bb398986.aspx refers to the "default asp.net handler" but does not identify a class or give any indication how one might use it.
Any ideas on how I can do this? Is it possible?
Persistence pays off! This actually works, and since this information seems to be available pretty much nowhere I thought I'd answer my own question. Thanks to Robert for this post on instantiating things with internal constructors, this is the key.
http://www.rvenables.com/2009/08/instantiating-classes-with-internal-constructors/
public void ProcessRequest(HttpContext context) {
// the internal constructor doesn't do anything but prevent you from instantiating
// the factory, so we can skip it.
PageHandlerFactory factory =
(PageHandlerFactory)System.Runtime.Serialization.FormatterServices
.GetUninitializedObject(typeof(System.Web.UI.PageHandlerFactory));
string newTarget = "default.aspx";
string newQueryString = // whatever you want
string oldQueryString = context.Request.QueryString.ToString();
string queryString = newQueryString + oldQueryString!="" ?
"&" + newQueryString :
"";
// the 3rd parameter must be just the file name.
// the 4th parameter should be the physical path to the file, though it also
// works fine if you pass an empty string - perhaps that's only to override
// the usual presentation based on the path?
var handler = factory.GetHandler(context, "GET",newTarget,
context.Request.MapPath(context,newTarget));
// Update the context object as it should appear to your page/app, and
// assign your new handler.
context.RewritePath(newTarget , "", queryString);
context.Handler = handler;
// .. and done
handler.ProcessRequest(context);
}
... and like some small miracle, an aspx page processes & renders completely in-process without the need to redirect.
I expect this will only work in IIS7.
I'm you're using Routing in webforms you should be able to just add an ignore route for the specific .aspx files you want. This will then be handled by the default HttpHandler.
http://msdn.microsoft.com/en-us/library/dd505203.aspx
Another option is to invert the logic by handling the cases in which you do NOT want to return the default response and remap the others to your own IHttpHandler. Whenever myCondition is false, the response will be the "default". The switch is implemented as an IHttpModule:
public class SwitchModule: IHttpModule
{
public void Init(HttpApplication context)
{
context.PostAuthenticateRequest += app_PostAuthenticateRequest;
}
void app_PostAuthenticateRequest(object sender, EventArgs e)
{
// Check for whatever condition you like
if (true)
HttpContext.Current.RemapHandler(new CustomHandler());
}
public void Dispose()
}
internal class CustomHandler: IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.Write("hallo");
}
public bool IsReusable { get; }
}

How do I share a function that uses "Response" or "Request" in ASP.NET?

I'd like to have a utility function that conditionally updates my request and response across several pages in my site.
Using a standard .CS class doesn't seem to give me access to these objects. How can I (generall speaking) create a utility function that checks for a cookie and update it across multiple pages?
You can always get at these things via
System.Web.HttpContext.Current.Request
System.Web.HttpContext.Current.Response
HttpContext Class and the Current Property
Encapsulates all HTTP-specific information about an individual HTTP request.
And to manage some cookie value throughout your site I would suggest either create a BasePage class that all of your Pages inherited from and do the checks there:
public class BasePage : System.Web.UI.Page
{
protected override void OnPreRender(EventArgs e)
{
UpdateCookie();
base.OnPreRender(e);
}
}
do the same in your MasterPage:
public class SiteMasterPage : MasterPage
{
protected override void OnPreRender(EventArgs e)
{
UpdateCookie();
base.OnPreRender(e);
}
}
public static void UpdateCookie()
{
HttpContext context = System.Web.HttpContext.Current;
HttpCookie cookie = context.Response.Cookies.Get("Update")
?? new HttpCookie("Update");
int value = 0;
int.TryParse(cookie.Value, out value);
value++;
cookie.Expires = DateTime.Now.AddDays(30);
cookie.Value = value.ToString();
context.Response.Cookies.Set(cookie);
}
use HttpContext.Current.Request and HttpContext.Current.Response
Use the fully qualified namespace:
System.Web.HttpContext.Current.Request
System.Web.HttpContext.Current.Response
-- or --
using System.Web.HttpContext.Current;
Then you should be able to access Request/Response throughout your class.
There are several ways to do this. Other have mentioned doing this with System.Web.HttpContext.Current, but I'd think (guessing from what I think your intent is) that doing this on a method that runs on load on your master pages is a better idea.

System.Web.Routing with WebForms - picking up variables in the target page

I have the pattern User/{domain}/{username} set up via Routing. Everything works except for one thing. I can't figure out how to get the domain and username variables passed to my redirected page. Below is my GetHttpHandler method from my IRouteHandler implementation.
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
string basePath;
basePath = "~/UserPage.aspx";
string domain = requestContext.RouteData.GetRequiredString("domain");
string username = requestContext.RouteData.GetRequiredString("username");
string virtualPath =
string.Format(basePath + "?domain={0}&username={1}", domain, username);
return (Page)BuildManager.CreateInstanceFromVirtualPath(virtualPath, typeof(Page));
}
I get the error from the last line of code:
UserPage.aspx?domain=SOMEDOMAIN&username=SOMEUSER is not a valid virtual path.
So how are you supposed to pass variables to the target page? what am I missing?
I think I solved this one myself.
Found this loop
foreach (KeyValuePair<string, object> token in requestContext.RouteData.Values)
{
requestContext.HttpContext.Items.Add(token.Key, token.Value);
}
from http://www.codethinked.com/post/2008/08/20/Exploring-SystemWebRouting.aspx
Its like the 4th code sample down.
UPDATE:
Not sure if this will work... requestContext.HttpContext seems to be "readonly". Back to the drawing board.
UPDATE 2:
Looks like this will work if you add in a reference to System.Web.Abstractions
Started mucking around with things and saw the IHttpHandler interface provides the RequestContext to the GetHttpHandler method.
So, I modified my base page class (I always put a layer between System.Web.UI.Page and my own pages, calling it BasePage or similar just for the purpose). So I added a public property on PVBasePage to receive a RequestContext object.
public RequestContext RequestContext { get; set; }
Then, my Routing class code is as follows:
IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)
{
// create the page object as my own page...
var page = BuildManager.CreateInstanceFromVirtualPath(VirtualPath
, typeof(PVBasePage)) as PVBasePage;
// pass in the request context
page.RequestContext = requestContext;
// return this page in the form of a IHttpHandler
return page as IHttpHandler;
}
So instead of, as in the sample code, creating the instance directly as the IHttpHandler, I create it as my own page. Set the request context property, and then return the page to the caller AS a IHttpHandler.
Tested and it works. WOO HOO!
Then in the instance page, you can hit the RequestContext.GetValues collection to read out your passed in parameters.
HTH
#B.Tyndall
I just got this working with a solution similar to yours.
found at: http://msmvps.com/blogs/luisabreu/archive/2008/03/12/using-the-routing-mvc-api-with-classic-asp-net.aspx
foreach (var aux in requestContext.RouteData.Values)
{
HttpContext.Current.Items[aux.Key] = aux.Value;
}
So in effect you're no longer using the Request.QueryString but instead Context.Items collection
HttpContext.Current.Items["RouteName"]
or
Context.Items["RouteName"]
It appears as though other are also taking the route (no pun intended) of putting the parameters in the context Items collection.
http://bbits.co.uk/blog/archive/2008/05/19/using-asp.net-routing-independent-of-mvc---passing-parameters-to.aspx
I combined a couple of these approaches for pages that have a specific parameter, I created a UserNameRouteHandler for pages that accept that type of parameter. In my PageBase class I checked the context items for that parameter and then set a property so that my pages that inherit from PageBase can use it.
public class UserNameRouteHandler : IRouteHandler
{
#region Implementation of IRouteHandler
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
string pageName = requestContext.RouteData.GetRequiredString("PageName");
string employeeUserName = requestContext.RouteData.GetRequiredString("UserName");
if(!string.IsNullOrEmpty(employeeUserName))
{
requestContext.HttpContext.Items["UserName"] = employeeUserName;
}
pageName = pageName.ToLower() == "home" ? "default" : pageName;
string virtualPath = string.Format("~/{0}.aspx", pageName);
return (Page)BuildManager.CreateInstanceFromVirtualPath(virtualPath, typeof(Page));
}
#endregion
}
And in my OnLoad of PageBase I set the property to pages that need it can have it...definitely looking for a more elegant solution though.
protected override void OnLoad(EventArgs e)
{
if (!IsPostBack)
{
if (Context.Items["UserName"] != null)
{
EmployeeUserName = Context.Items["UserName"].ToString();
}
}
base.OnLoad(e);
}

How do I convert an ASP.NET page using Ajax webmethods to an Ajax-enabled servercontrol?

In this tutorial I am reading, Dave Ward creates a page that shows the server date in a label without using the update panel.
I am trying to learn how to create servercontrols that use ajax for partial postbacks where methods within the control are called from clientscript generated by the same control, and I think that learning how to convert this page to a server control would be a help me understand what servercontrols use instead of webmethods to expose their methods to clientscript.
I created the page, codebehind, and javascript exactly as the article indicated and got the sample to work.
So, to start trying to convert this to a servercontrol, I moved Dave's Javascript for the page into a file, ~tests/JScript.js:
function UpdateTime() {
PageMethods.GetCurrentDate(OnSucceeded, OnFailed);
}
function OnSucceeded(result, userContext, methodName) {
$get('Literal1').innerHTML = result;
}
function OnFailed(error, userContext, methodName) {
$get('Literal1').innerHTML = "An error occured.";
}
And put the following class in my App_Code:
namespace foo
{
/// <summary>
/// Summary description for ServerControlTest
/// </summary>
public class ServerControlTest : CompositeControl, IScriptControl
{
ScriptManager sm;
protected override void OnPreRender(EventArgs e)
{
if (!this.DesignMode)
{
// Test for ScriptManager and register if it exists
sm = ScriptManager.GetCurrent(Page);
if (sm == null)
throw new HttpException("A ScriptManager control must exist on the current page.");
sm.RegisterScriptControl(this);
sm.EnablePageMethods = true;
}
base.OnPreRender(e);
}
protected override void OnLoad(EventArgs e)
{
Literal lit = new Literal();
lit.Text = "<span ID=\"Literal1\" runat=\"server\">test</span><input id=\"Button1\" type=\"button\" value=\"button\" onclick=\"UpdateTime();\" />";
this.Controls.Add(lit);
}
protected override void Render(HtmlTextWriter writer)
{
if (!this.DesignMode)
sm.RegisterScriptDescriptors(this);
base.Render(writer);
}
[WebMethod]
public static string GetCurrentDate()
{
return DateTime.Now.ToString();
}
#region IScriptControl Members
IEnumerable<ScriptDescriptor> IScriptControl.GetScriptDescriptors()
{
return null;
}
IEnumerable<ScriptReference> IScriptControl.GetScriptReferences()
{
ScriptReference reference = new ScriptReference();
reference.Path = ResolveClientUrl("~/tests/JScript.js");
return new ScriptReference[] { reference };
}
#endregion
}
}
Now, in my sample page, when I click the button, I get this error:
PageMethods is not defined
[Break on this error] PageMethods.GetCurrentDate(OnSucceeded, OnFailed);
How do I call GetCurrentDate from the clientscript that my control registers?
There is actually no fully encapsulated method for implementing AJAX callbacks against methods of a server control yet, as of v3.5. It's a very frustrating limitation.
The most common solution is to create an HttpHandler in your server control's assembly, then require that the handler be registered in the web.config. Look at how ASP.NET AJAX's ScriptResource.axd is wired up in the web.config in ASP.NET AJAX 1.0, for example.

Resources