1. URL rewriting is common, but basically most URL rewriting does not support relative paths of pages. If you want to add a URL to a developed project, there is still pressure, the second is that, for example, Microsoft's URL rewriting is handled based on regular expressions, which is very good, but there are also deficiencies, that is, it is not convenient to locate what parameters a page can only have.
I think there are several problems to solve:
1. Solve file files such as slice js that cannot use relative paths
2. Fixed several parameters and optional parameters for a page.
The following is how to solve these problems.
Add the handler MyHttpModule. Below is a simple handler (I just made a simple one without considering the performance, in addition, if I write a dead url, rewrite it to no extension)
Copy codeThe Code is as follows: using System;
Using System. Collections. Generic;
Using System. Web;
Using System. IO;
Using System. Text;
Namespace MyClass
{
Public class MyHttpModule: IHttpModule
{
# Region IHttpModule Member
/// <Summary>
/// Release all resources
/// </Summary>
Public void Dispose ()
{
}
/// <Summary>
/// Initialize the module and prepare it for processing requests
/// </Summary>
/// <Param name = "context"> A System. web. httpApplication, which provides.. NET application, and access to common methods, properties, and events of all application objects </param>
Public void Init (HttpApplication context)
{
Context. AuthorizeRequest + = new
EventHandler (this. BaseModuleRewriter_AuthorizeRequest );
}
/// <Summary>
/// This occurs when the security module has verified user authorization.
/// </Summary>
/// <Param name = "sender"> </param>
/// <Param name = "e"> </param>
Protected virtual void BaseModuleRewriter_AuthorizeRequest (
Object sender, EventArgs e)
{
System. Web. HttpApplication app = (System. Web. HttpApplication) sender;
Rewrite (app. Request. Path, app );
}
/// <Summary>
/// Rewrite the url
/// </Summary>
/// <Param name = "requestedPath"> virtual path of the url </param>
/// <Param name = "app"> </param>
Protected void Rewrite (string requestedPath, System. Web. HttpApplication app)
{
List <string> qeryString;
String virtualPath;
String inputFile = GetInputFile (app. Context, out virtualPath, out qeryString); // obtain the actual file information
If (System. IO. Path. GetExtension (inputFile) = ". aspx") // if it is An aspx file, the reserved url is overwritten.
{
App. context. rewritePath (requestedPath, string. empty, string. empty); // I have not processed the query parameters here, that is, the Request. queryString information. If qeryString is taken and then processed as a string
Return;
}
App. Context. RewritePath (virtualPath, string. Empty, app. Context. Request. QueryString. ToString (); // use the path found for other files.
}
/// <Summary>
/// Obtain the absolute path and virtual path corresponding to the url and query parameters
/// </Summary>
/// <Param name = "context"> </param>
/// <Param name = "virtualPath"> virtual path </param>
/// <Param name = "qeryString"> If the query parameter is null, use HttpContext. Request. QueryString. </param>
/// <Returns> absolute url </returns>
Public static string GetInputFile (HttpContext context, out string virtualPath, out List <string> qeryString)
{
String executionFilePath = context. Request. AppRelativeCurrentExecutionFilePath. Remove (0, 2); // obtain the current virtual path and kill "~ /"
String inputFile = context. Request. PhysicalPath; // obtain the absolute path of the current url
VirtualPath = context. Request. AppRelativeCurrentExecutionFilePath;
QeryString = null;
List <string> qeryList = new List <string> ();
If (! File. Exists (inputFile) // determines whether the File Exists, that is, the url that has not been overwritten is used to obtain resources using the absolute path, etc.
{
Bool B = false;
String fileName;
String extension;
String applicationPath = context. Request. PhysicalApplicationPath; // obtain the website's directory
Var tempPath = GetFileInfo (inputFile, out fileName, out extension );
While (! B) // obtain a valid file directory cyclically Based on the directory
{
B = File. Exists (tempPath + "\" + extension); // checks whether the File Exists.
If (tempPath + "\" = applicationPath) // if the root directory is not found, you do not need to query
{
Break;
}
If (! String. IsNullOrWhiteSpace (fileName ))
{
QeryList. Add (fileName); // if it does not exist, this is the parameter such as http: // localhost: 4688/WebForm1/2011/(corresponding to http: // localhost: 4688/WebForm1.aspx? XXXXX = 2011)
}
TempPath = GetFileInfo (tempPath, out fileName, out extension );
}
If (B) // if yes, copy the path to the output or return parameter.
{
InputFile = tempPath + "\" + extension;
VirtualPath = "~ /"+ InputFile. Replace (applicationPath, null );
}
If (Path. GetExtension (extension) = ". aspx") // if it is asp.net, copy the list to the output parameter qeryString.
{
QeryString = qeryList;
}
}
Return inputFile;
}
/// <Summary>
/// Obtain whether the specified directory + file is valid
/// </Summary>
/// <Param name = "inputFile"> directory </param>
/// <Param name = "fileName"> </param>
/// <Param name = "extension"> </param>
/// <Returns> </returns>
Private static string GetFileInfo (string inputFile, out string fileName, out string extension)
{
Var tempPath = Directory. GetParent (inputFile). FullName; // obtain the parent Directory of the imported Directory.
FileName = inputFile. Replace (tempPath + "\", null); // obtain the subdirectory name
Extension = Path. GetExtension (inputFile); // get the extension
If (string. IsNullOrWhiteSpace (extension) // if the extension is null, it is considered as An aspx file.
{
Extension = fileName + ". aspx ";
}
Else
{
Extension = fileName + extension;
}
Return tempPath;
}
# Endregion
}
}
Because I still pass in the overwritten path when processing the aspx page, we also add a class that inherits IHttpHandlerFactory.
The Code is as follows:Copy codeThe Code is as follows: using System;
Using System. Collections. Generic;
Using System. Linq;
Using System. Text;
Using System. Web;
Using System. IO;
Using System. Web. UI;
Namespace MyClass
{
Public class MyHttpHandlerFactory: IHttpHandlerFactory
{
# Region IHttpHandlerFactory Member
/// <Summary>
/// Return the instance of the class implementing the System. Web. IHttpHandler Interface
/// </Summary>
/// <Param name = "context"> System. web. an instance of the HttpContext class that provides reference to internal Server objects (such as requests, Response, Session, and Server) used to provide services for HTTP requests. </param>
/// <Param name = "requestType"> HTTP data transmission method (GET or POST) used by the client </param>
/// <Param name = "url"> System. Web. HttpRequest. RawUrl of the requested resource </param>
/// <Param name = "pathTranslated"> System. Web. HttpRequest. PhysicalApplicationPath of the requested resource </param>
/// <Returns> the new System. Web. IHttpHandler object that processes the request </returns>
Public IHttpHandler GetHandler (HttpContext context, string requestType, string url, string pathTranslated)
{
List <string> qeryString;
String virtualPath;
String inputFile = MyHttpModule. GetInputFile (context, out virtualPath, out qeryString); // This is the same as where
Object [] obj = new object [] {};
Dictionary <string, string> qeryStringDictionary = new Dictionary <string, string> ();
Var export emembers = System. web. compilation. buildManager. getCompiledType (virtualPath ). getMember ("ReceiveParameters"); // obtain all the members accessing the current page. (This is my own method. I want to build it into the mvc mode, but it may not be very good)
System. Reflection. MethodInfo export eparameters = null;
If (qeryString! = Null & qeryString. Count> 0) // if no parameter is found, no reflection is performed.
{
Foreach (System. Reflection. MemberInfo receiveMember in receiveMembers) // traverses all registreparameters members
{
If (export emember. MemberType = System. Reflection. MemberTypes. Method) // because the above obtained is a member, but what we need is that all methods must be judged.
{
System. Reflection. MethodInfo methodInfo = receiveMember as System. Reflection. MethodInfo;
If (methodInfo! = Null)
{
Var parameters = methodInfo. GetParameters (); // gets all parameters of the ReceiveParameters method.
Int optionalCount = parameters. Count (I => I. IsOptional); // obtain the number of optional parameters in the ReceiveParameters parameter.
Bool B = qeryString. Count = parameters. Length-optionalCount;
If (qeryString. Count = parameters. Length | B) // if the currently queried parameters or all the parameters of ReceiveParameters-The deselected query parameters are equal
{
Export eparameters = methodInfo; // record this method
Int I = 0;
Obj = new object [parameters. Length]; // record the parameter value, which will be used when ReceiveParameters is called later.
For (; I <parameters. Length; I ++)
{
String name = parameters [I]. Name; // obtain the parameter name.
String value = string. Empty;
If (qeryString. Count> I) // the string to be queried if the ReceiveParameters parameter is not available
{
Value = qeryString [I];
}
Obj [I] = value; // Save the query string and use it when calling ReceiveParameters.
QeryStringDictionary. Add (name, value); // Add it to the custom set
}
Break;
}
}
}
}
If (paieparameters = null) // determine whether the file has been found. if not, assign all the previously found file information to the overwritten file information, that is, the file does not exist.
{
VirtualPath = context. Request. Path;
InputFile = context. Request. PhysicalPath;
}
}
Var temp = System. Web. UI. PageParser. GetCompiledPageInstance (virtualPath, inputFile, context); // compile the page
If (receiveParameters! = Null) // The content in this should actually be written into ReleaseHandler, but I wrote it here
{
System. Web. UI. Page page = (System. Web. UI. Page) temp;
Page. init + = new EventHandler (page_Init); // Add an event and // Add a PageBase class. In this way, you can put the actual path information and query parameters in
Sss = paieparameters;
Sssobj = obj;
// Export eparameters. Invoke (temp, obj );
}
Return temp;
}
Public System. Reflection. MethodInfo sss {get; set ;}
Public object [] sssobj {get; set ;}
Protected void page_Init (object sender, EventArgs e)
{
Sss. Invoke (sender, sssobj); // when the page is executed here, call the ReceiveParameters method and make other judgments here... But does not comply with programming specifications (my understanding)
}
/// <Summary>
/// Enable the factory to reuse existing handler instances
/// </Summary>
/// <Param name = "handler"> System. Web. IHttpHandler object to be reused </param>
Public void ReleaseHandler (IHttpHandler handler)
{
}
# Endregion
}
}
Page code is to put more methods
/// <Summary>
/// If multiple parameters are required, manually add them, for example, public void paieparameters (string name, string value) after the page is compiled, the method is automatically run according to the parameters and the parameter value is transferred.
/// </Summary>
/// <Param name = "name"> the parameter name is name </param>
Public void paieparameters (string name)
{
Var temp = Request;
}
Url is fixed. Let's take a look at what we are trying to get rid...
I only wrote to remove the entity state of the event, and then manually stimulate the event of the control, and write the code in the url to solve the problem as follows:Copy codeThe Code is as follows: protected void page_Init (object sender, EventArgs e)
{
Sss. Invoke (sender, sssobj );
Page page = (Page) sender;
Foreach (string name in page. Request. Form. AllKeys) // you can specify _ EVENTARGUMENT to hide all the dictionaries in form.
{
Try
{
System. Web. UI. Control control = page. FindControl (page. Page. Request. Form [name]); // find this Control
If (control! = Null)
{
String value = page. Request. Form [Page. postEventSourceID];
IPostBackEventHandler ip = control as IPostBackEventHandler;
If (ip! = Null) // It can be converted to IPostBackEventHandler.
{
Ip. RaisePostBackEvent (value );
Break;
}
IPostBackDataHandler backDataHandler = control as IPostBackDataHandler;
If (backDataHandler! = Null) // if it can be converted to IPostBackDataHandler, the value of the hidden field of _ EVENTTARGET is passed to the control and the change event is triggered.
{
System. Collections. Specialized. NameValueCollection nameValueCollection = new System. Collections. Specialized. NameValueCollection ();
NameValueCollection. Add (page. Request. Form [control. ClientID], page. Request. Form [control. ClientID]);
BackDataHandler. LoadPostData (control. ClientID, nameValueCollection );
BackDataHandler. RaisePostDataChangedEvent ();
}
}
Break;
}
Catch
{
}
}
}
This is the end of simple processing,
I hope you will help me to improve the processing mechanism, because I do not know much about the processing mechanism of ASp.net after all...