How to compress asp.net page in code level? - asp.net

I added a method called Application_PreRequestHandlerExecute in global.ascx like this:
void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
string cTheFile = HttpContext.Current.Request.Path;
string sExtentionOfThisFile = System.IO.Path.GetExtension(cTheFile);
if (sExtentionOfThisFile.Equals(".aspx", StringComparison.InvariantCultureIgnoreCase))
{
HttpApplication httpApp = (HttpApplication)sender;
string acceptEncoding = httpApp.Request.Headers["Accept-Encoding"];
if (string.IsNullOrEmpty(acceptEncoding))
{
return;
}
acceptEncoding = acceptEncoding.ToLower();
System.IO.Stream requestStream = httpApp.Response.Filter;
if (acceptEncoding.Contains("gzip"))
{
httpApp.Response.Filter = new System.IO.Compression.GZipStream(requestStream,
System.IO.Compression.CompressionMode.Compress);
httpApp.Response.AppendHeader("Content-Encoding", "gzip");
}
else if (acceptEncoding.Contains("deflate"))
{
httpApp.Response.Filter = new System.IO.Compression.DeflateStream(requestStream,
System.IO.Compression.CompressionMode.Compress);
httpApp.Response.AppendHeader("Content-Encoding", "deflate");
}
}
}
It worked when browse normal page.
but if a page contains UPDATE-PANEL error will happen.
I get a PageRequestParserException.
when update-panel async post back, this error happens.
any idea?

I "fixed" by set the EnableEventValidation to false on my page and move compress logic to page's constructor.
Obviously this is not a good solution(close validation).
If anybody know a good solution, pls let me know.
and found that if the project's framework version is 3.5, all works fine,
but if the version is 2.0. this error will happen.

Related

JSON Compression attribute

I have been using a compression attribute I found on the web, which is working very well for us.
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpRequestBase request = filterContext.HttpContext.Request;
string acceptEncoding = request.Headers["Accept-Encoding"];
if (string.IsNullOrEmpty(acceptEncoding)) return;
acceptEncoding = acceptEncoding.ToUpperInvariant();
HttpResponseBase response = filterContext.HttpContext.Response;
if (acceptEncoding.Contains("GZIP"))
{
response.AppendHeader("Content-encoding", "gzip");
response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
}
else if (acceptEncoding.Contains("DEFLATE"))
{
response.AppendHeader("Content-encoding", "deflate");
response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
}
}
the problem I have is that when an exception is thrown, then the screen displays the compressed content (I think!).. it looks like this..
xi��V�4��^ :b���$I"i#!c{��`$c��'wy�N�������H:��38�YS�b?ߕ�!`WSϙ��萧̬n��H����:V(ylZ� �ωԱ��Ϟӱ=�囥�ֺ���V��/>�^R���$٣����T�����J�oRݬz���?6$�<��KՔ��B0�x��V$�����F�h+Ǐ���!���0J��ɒ�h��+VR�p�ۊ�������!��-cccs�Z�%��2{�Ѿ��r�����۩/�,�n��n�f���tܳu�}����.+t��]���̆�����,�c��-�H0)J������dP�� �� ��/�|��#�Z�]O
My question is, is it possible to somehow work around this? Any way I can get this action to work nicely with exceptions?
You can remove the compression filter in Application_Error:
protected void Application_Error(object sender, EventArgs e)
{
(sender as HttpApplication).Response.Filter = null;
}
Alternatively, you can try updating the Content-Encoding response header appropriately but I haven't tried that so not sure if it's going to work.

Set culture using cookie in asp.net, not updated

I'm using asp.net and want to make it possible for the user to set the culture to use in the website by himself. In MasterPage I have the following code to set a language cookie:
protected void Page_Load(object sender, EventArgs e) {
if (Request.QueryString["setLanguage"] != null)
{
HttpCookie languageCookie = new HttpCookie("language");
languageCookie.Value = Request.QueryString["setLanguage"];
languageCookie.Expires = DateTime.Now.AddDays(10);
Response.SetCookie(languageCookie);
}
}
In Global.asax I use the cookie like this:
protected void Application_BeginRequest(object sender, EventArgs e) {
HttpCookie languageCookie = System.Web.HttpContext.Current.Request.Cookies["language"];
if (languageCookie.Value != null)
{
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(language);
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(language);
}
}
The problem is that after I set the cookie with Response.SetCookie I need to reload the page to get the new language. How can I make my code so when the user set a new language the page is reloaded with the new language directly?
You can do
Response.Redirect(Request.PathAndQuery);
But why not just set the language after setting the Cookie? You can even use the BeginRequest event to check for specific input being posted and use it as an alternative condition for setting the language.
I had the same issue with the language being selected by the user. In order for it to work you have to do it on
protected override void InitializeCulture()
{
HttpCookie languageCookie = System.Web.HttpContext.Current.Request.Cookies["language"];
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(language);
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(language);
}
In order for it to work on every page of the site, I created a class that inherited from System.Web.UI.Page and implemented there
public class myBasePage : System.Web.UI.Page
{
protected override void InitializeCulture()
{
HttpCookie languageCookie = System.Web.HttpContext.Current.Request.Cookies["language"];
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(language);
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(language);
base.InitializeCulture();
}
}
from then on I had all my pages inherit from myBasePage.
This way, I used a Server (Postback) control to set the language and the page would get reloaded, and the language would be set.
If you are using Asp.Net MVC
//A foreigner, has possibly brew a cookie for me
public class SpeakNativeTongueAttribute : ActionFilterAttribute, IActionFilter
{
const string cookieName = "culture";
void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
{
var cookieKeys = filterContext.RequestContext.HttpContext.Request.Cookies.AllKeys;
if (cookieKeys.Contains(cookieName))
{
//eat the cookie
var theCultureCookie = filterContext.RequestContext.HttpContext.Request.Cookies[cookieName];
var theCulture = theCultureCookie.Value;
//say thanks in native tongue
System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.GetCultureInfo(theCulture);
System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo(theCulture);
}
else
{
//Didn't receive a cookie, don't speak their language, those bastards!
}
}
}

Silverlight OOB WebBrowser Exception

I've got an oob app with a webbrowser on it.
The webbrowser source is databound with a URI defined by me. The URI has a path to a webpage from my server that displays a PDF file from its hardrive.
Note that all this is done on a local network.
URI example: uri = new Uri(#"http://ServerName/ProjectName/PDFViewer.aspx?pdf=somePDF.pdf");
Page code-behind:
protected void Page_Load(object sender, EventArgs e)
{
string myURL = Request.Url.ToString();
string[] ParamArray = Regex.Split(myURL, "pdf=");
string Params = ParamArray[ParamArray.Length - 1];
if (Params.Length > 0)
{
Filename = Regex.Replace(Params, #"//", #"\\"); ;
if (File.Exists(Filename))
{
Response.ContentType = "Application/pdf";
Response.WriteFile(Filename); //Write the file directly to the HTTP content output stream.
Response.End();
}
else
this.Title = "PDF Not Found";
}
}
protected void Page_Load(object sender, EventArgs e) { string myURL = Request.Url.ToString(); string[] ParamArray = Regex.Split(myURL, "pdf="); //If the URL has parameters, then get them. If not, return a blank string string Params = ParamArray[ParamArray.Length - 1]; if (Params.Length > 0) { //to the called (src) web page Filename = Regex.Replace(Params, #"//", #"\\"); ; if (File.Exists(Filename)) { Response.ContentType = "Application/pdf"; Response.WriteFile(Filename); //Write the file directly to the HTTP content output stream. Response.End(); } else this.Title = "PDF Not Found"; } }
The first time I set the WebBrowser source everything it displays the PDF. But when I set the URI one second time the app throws an exception: Trying to revoke a drop target that has not been registered (Exception from HRESULT: 0x80040100).
I've done a few tests and here are the results:
1º new Uri(#"http://ServerName/ProjectName/PDFViewer.aspx?pdf=somePDF.pdf");
2º new Uri(#"http://ServerName/ProjectName/PDFViewer.aspx?pdf=someOtherPDF.pdf"); ->error
1º new Uri(#"http://ServerName/ProjectName/PDFViewer.aspx?pdf=somePDF.pdf");
2º new Uri(#"http://www.google.com"); ->error
1º new Uri(#"http://www.google.com");
2º new Uri(#"http://www.microsoft.com");
2º new Uri(#"http://ServerName/ProjectName/PDFViewer.aspx?pdf=somePDF.pdf");
3º new Uri(#"http://ServerName/ProjectName/PDFViewer.aspx?pdf=someOtherPDF.pdf"); ->error
I also forgot to say that when running the app from my browser (using a HTMLHost) the pages display just fine. Opening the pages using a browser will also work well.
It must be some problem with my aspx page. Any ideas?
Pedro
I've managed to resolve this by creating a new browser for each page. If you know of a more elegant solution please share.
I am not sure if I'm following the question/problem correctly but maybe loading the pages async and then assigning to webbrowser? Forgive me if I am off-base here.
public void ShowLink(string linkUrl)
{
if (App.Current.IsRunningOutOfBrowser)
{
var pageRequest = new WebClient();
pageRequest.DownloadStringCompleted += pageRequest_DownloadStringCompleted;
pageRequest.DownloadStringAsync(new Uri(linkUrl, UriKind.Absolute));
}
}
void pageRequest_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
webBrowserLink.NavigateToString(e.Result.ToString());
}

Get session object from sessionID in ASP.Net

Is there anyway to get a session object from a sessionID?
I have a small project using a Flash upload to let a user upload their file to the server, but the problem is that Flash has some error when sending the session and cookie (in Firefox or Chrome, but not IE), so I found a solution to fix this problem: sending the sessionID through Flash to the server, and on the server, decode sessionID back to the session object, but I don't how to do it. I'm using ASP.NET and C#.
Can anyone advise me on what to do?
The link proposed by Moo-Juice is no longer working.
I used the code provided in this page:
http://snipplr.com/view/15180/
It worked like a charm.
If the link would become broken, here is the code:
void Application_BeginRequest(object sender, EventArgs e)
{
try
{
string session_param_name = "ASPSESSID";
string session_cookie_name = "ASP.NET_SESSIONID";
string session_value = Request.Form[session_param_name] ?? Request.QueryString[session_param_name];
if (session_value != null) { UpdateCookie(session_cookie_name, session_value); }
}
catch (Exception) { }
try
{
string auth_param_name = "AUTHID";
string auth_cookie_name = FormsAuthentication.FormsCookieName;
string auth_value = Request.Form[auth_param_name] ?? Request.QueryString[auth_param_name];
if (auth_value != null) { UpdateCookie(auth_cookie_name, auth_value); }
}
catch (Exception) { }
}
void UpdateCookie(string cookie_name, string cookie_value)
{
HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(cookie_name);
if (cookie == null)
{
HttpCookie cookie1 = new HttpCookie(cookie_name, cookie_value);
Response.Cookies.Add(cookie1);
}
else
{
cookie.Value = cookie_value;
HttpContext.Current.Request.Cookies.Set(cookie);
}
}

How to log POSTed forms submissions?

Back in the ASP classic days when i needed to write out the name/value pairs of forms submitted by POST i thru this loop into the page:
on error resume next
for each x in Request.Form
Response.AppendToLog x & "=" & Request(x)
next
It threw all the form fields and values into the log just as GETs are. Does IIS7 .net give me any better method? (this is for the dev/testing portion of the project i don't have any concern about the space or cycles used to accomplish this).
thx
You can create an http module to log all posts. It allows you to log outside of the pages, a single point of logging instead of having to add the logic to all pages where you want to log activity.
Here you have some of the code. You would have to avoid logging viewstate since is tons of useless information. So you have to add some logic to achieve this.
public class ActivityLogModule: IHttpModule
{
public void Init(HttpApplication application)
{
application.EndRequest += (new EventHandler(this.Application_EndRequest));
}
private void Application_EndRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
if (RecordActivity(context))
{
ActivityLogger.Instance.Log(application.Context.User.Identity.Name,
application.Context.Request.Url.AbsoluteUri,
application.Context.Request.Form.ToString());
}
}
public void Dispose(){}
protected bool RecordActivity(HttpContext context)
{
if (!context.Request.RequestType.Equals("POST"))
{
return false;
}
return true;
}
}
You could have something like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
LogPostValues();
}
private void LogPostValues()
{
string logPath = #"C:\PostedValuesLog.txt";
StringBuilder sb = new StringBuilder();
sb.AppendFormat("Logging: {0}", Request.Path);
sb.Append("Form Values");
foreach (string key in Request.Form)
{
string val = Request.Form[key];
sb.AppendFormat("{0} = {1}<br/>", key, val);
}
sb.Append(Environment.NewLine);
sb.Append("QueryString Values");
foreach (string key in Request.QueryString)
{
string val = Request.QueryString[key];
sb.AppendFormat("{0} = {1}<br/>", key, val);
}
sb.Append(Environment.NewLine);
sb.Append(Environment.NewLine);
sb.Append(Environment.NewLine);
File.AppendAllText(logPath, sb.ToString());
}
This is a crude method though and shouldn't really be used in production code. However, as this is just for development & testing, it should suffice to track what data is being posted to your page via the querystring and form.

Resources