I am new in asp.net. i want to know about the generic handlers in asp.net
and how and where it use?
Could you help me?
Generic handlers are the .NET components that implement the System.Web.IHttpHandler interface. Any class that implements the IHttpHandler interface can act as a target for the incoming HTTP requests. Page is also generic handler. In general generic handlers have an extension of ASHX.
You can find example here
Handlers are used when you want to avoid the overhead of a regular asp.net page. Practical examples include image processing or handling AJAX requests.
See Using HTTP Modules and Handlers to Create Pluggable ASP.NET Components.
Some ASP.NET files are dynamically generated. They are generated with C# code or disk resources. These files do not require web forms. Instead, an ASHX generic handler is ideal. It can dynamically return an image from a query string, write XML, or any other data.
Ashx File is nothing but just like an aspx page.They're equivalent to custom handlers written in C Sharp or Visual Basic.NET in that they contain classes that fully implement IHttpHandler. They're convenient in the same way ASPX files are convenient. You simply surf to them and they're compiled automatically.
When WebForms(aspx)to be used
Simple Html Pages
Asp.net Custom Controls
Simple Dyanamic Pages
When Handlers(ashx) to be used
Binary files
Dynamic Image Views
Performance critical web pages
xml files
Minimal Web Pages
ASHX Generic Handler is a concept to return dynamic content. It is used to return ajax calls, image from a query string, write XML, or any other data.
I have used it to return MP4 file from query string. Please find the following code.
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
namespace ESPB.CRM.Web.UI.VideoUploading
{
public class FileCS : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
int id = int.Parse(context.Request.QueryString["id"]);
byte[] bytes;
string contentType;
string strConnString = ConfigurationManager.ConnectionStrings["dbconnection"].ConnectionString;
string name;
using (SqlConnection con = new SqlConnection(strConnString))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = "select Name, Data, ContentType from VideoUpload where Id=#Id";
cmd.Parameters.AddWithValue("#Id", id);
cmd.Connection = con;
con.Open();
SqlDataReader sdr = cmd.ExecuteReader();
sdr.Read();
bytes = (byte[])sdr["Data"];
contentType = sdr["ContentType"].ToString();
name = sdr["Name"].ToString();
con.Close();
}
}
context.Response.Clear();
context.Response.Buffer = true;
context.Response.AppendHeader("Content-Disposition", "attachment; filename=" + name);
context.Response.ContentType = contentType;
context.Response.BinaryWrite(bytes);
context.Response.End();
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
Here I have created FileCS.ashx file.
Where I inherit IHttpHandler interface. and wrote ProcessRequest(HttpContext context) function, which will run default while call the file. And context.Request.QueryString[] will get the parameter. Here I am passing id as parameter. IsReusable() function can be use for good performance.
Related
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; }
}
I have some ASP.net code that I am working with and I am running into a silent failing.
using System;
using System.IO;
using System.Web;
using System.Web.Services;
public partial class _Default : System.Web.UI.Page
{
[WebMethod(EnableSession=false)]
public static string ProcessData()
{
string chartFile = HttpContext.Current.Server.MapPath("~/Example/chartData.json");
//StreamWriter chartData = new StreamWriter(chartFile);
StreamWriter chartData = new StreamWriter("C:\\_Sites\\Example\\chartData.json");
chartData.WriteLine("Test This Out");
chartData.Flush();
chartData.Close(); // Close the instance of StreamWriter.
chartData.Dispose(); // Dispose from memory.
return chartFile;
}
}
The code I have commented out fails silently. I know the path is being correctly placed into chartFile. I think StreamWriter is not super happy about the var possibly due to the : and \ not being escaped in the string.
I cannot provide a direct path due to the nature of the deployment server. Any suggestions on how to get StreamWriter to play nice with the string contained in chartFile?
Thanks in advance.
I am implementing a dynamic ASMX web service via a custom HttpHandler, and my web service has recently stopped generating WSDL automatically. When I use ?WSDL on the asmx url, I get the following error:
System.InvalidOperationException: XML Web service description was not found.
at System.Web.Services.Protocols.DiscoveryServerProtocol.WriteReturns(Object[] returnValues, Stream outputStream)
at System.Web.Services.Protocols.WebServiceHandler.WriteReturns(Object[] returnValues)
at System.Web.Services.Protocols.WebServiceHandler.Invoke()
This worked fine a while ago, so I'm wondering if there's a file permission problem somewhere.
A Google search does not return any reference to this particular situation.
I doubt that my code is relevant to the problem; it has not changed:
[WebService(Description = "...", Namespace = "...")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
public class MyWebService : System.Web.Services.WebService
{
[WebMethod]
void MyWebMethod() {}
}
public class VirtualWebServiceFactory : IHttpHandlerFactory
{
public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
{
WebServiceHandlerFactory wshf = new WebServiceHandlerFactory();
MethodInfo coreGetHandler = wshf.GetType().GetMethod("CoreGetHandler", BindingFlags.NonPublic | BindingFlags.Instance);
IHttpHandler handler = (IHttpHandler)coreGetHandler.Invoke(wshf, new object[] { typeof(MyWebService), context, context.Request, context.Response });
return handler;
}
}
Decompiling System.Web.Services.Protocols.DiscoveryServerProtocol.WriteReturns() reveals that it looks up the XML service description in a dictionary created somewhere else.
I was hoping that someone familiar with the DiscoverServerProtocol etc. might know under what circumstances the XML service description might fail to be built.
The following works just fine:
ServiceDescriptionReflector reflector = new ServiceDescriptionReflector();
reflector.Reflect(typeof(MyWebService), "...");
Navigating to MyWebService.asmx shows all the functions and allows testing them. But using ?WSDL gives the exception above.
Just for fun, try making your WebMethod public.
However, the real answer is to not screw around with .NET Framework code that's not meant to be called. What's wrong with just calling GetHandler? What are you trying to accomplish here that can't be accomplished without messing around in the internals of an obscure class?
Hmm, after many months, found out that the URL was being re-written to include other parameters than the ?WSDL, which made the private function choke.
What is the best practice to support data for asp.net 2.0-3.5 ajax web application?
I don't want to use update panels, just plain text data (JSON).
Should I use web services? Or is there another way.
Errrr... Use an .aspx page ? What are handlers for ?
You just have to create a generic base handler that will take care of json (de)serialization (e.g. using Json.net) and then implement handlers for your ajax calls.
public abstract class JsonHandlerBase<TInput, TOutput> : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "application/json";
TInput input = (TInput)context.Request; // Desesialize input
TOutput output = ProcessRequest(context, parameter);
string json = (string)output; // Serialize output
context.Response.Write(json);
}
public abstract TOutput ProcessRequest(HttpContext context, TInput input);
public bool IsReusable { get { return false; } }
}
This is just an example, it's up to you to decide want you need in your base handler.
You can use plain aspx pages or handlers and just output JSON. You do this by erasing all the Html in the aspx and then using Response.Write() in the code.
Then for the front end JS you can use JQuery or any other Ajax framework.
You may also want to check out Asp.Net MVC. MVC has a JsonResult resonse type and is very easy to use together with JQuery to get very good Ajax functionality.
I have a method on a page marked with the webmethod and scriptmethod tags..
The method returns a collection of objects to a jquery function as JSON data with no hassles and without me having to manually serialize it.
I am now trying to recreate that same method using a HTTPHandler and was wondering why i have to now manually serialize the data.
What makes the webmethod different?
Because an HTTP handler (kind of) sits above the ASP WebForms Stack, you are totally responsible for the workings and output of the handler.
You can utilise (almost) anything you can get your hands on within the .NET framework, but for sure, an HTTPHandler will be more work than an off-the-shelf solution provided by ASP.NET.
The ASP.NET page handler is only one
type of handler. ASP.NET comes with
several other built-in handlers such
as the Web service handler for .asmx
files.
You can create custom HTTP handlers
when you want special handling that
you can identify using file name
extensions in your application
See http://msdn.microsoft.com/en-us/library/ms227675(VS.85).aspx
Web method provides you a connection between your c# class and Js file. Nowadays Using Json is a best way to get the return message in a smart format for a js function or anywhere in js file.
Regards
For lesser work:
Move your method to an ASMX (Web Service):
You will benefit the built-in serialization provided by the ScriptService:
namespace WS{
[System.web.Script.Services.ScriptService()]
[System.Web.Services.WebService(Namespace:="http://tempuri.org/")]
public class WebService1 : System.Web.Services.WebService
{
[WebMethod]
public Person GetDummyPerson()
{
Person p = new Person();
p.Name = "John Wayne";
p.Age = 20;
}
[WebMethod]
public IList GetPersonsByAge(int age)
{
//do actual data retrieval
List result = new List();
result.add(new Person());
result.add(new Person());
return result;
}
}
class Person
{
String Name;
int Age;
}
}
On the client side:
WS.GetDummyPerson(function(p){
alert(p.Name + "-->" + p.Age);
});
WS.GetPersonsByAge(10,function(list){
for(var i=0;i<list.length;i++)
{
document.write(list[i].Name + "==>" + list[i].Age);
}
});