Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HttpContext, alternative approach to Context.Request.Unvalidated for pre .Net 4.5 servers

Tags:

c#

.net

I have a method in my project as per below which takes a HttpContext object and returns a string.

//returns the xml document as string
private static string GetXmlReceiptFromContext(HttpContext context)
{
    context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    context.Response.Cache.SetNoStore();
    context.Response.Cache.SetExpires(DateTime.MinValue);        
    return context.Request.Unvalidated.Form.Get("status");
}

The result of this is ultimately passed into a very important method that requires this string.

It appears that Context.Request.Unvalidated is only available from .Net 4.5. I need to alternative approach to this method for our servers which do not have .Net 4.5 and will be making use of this assembly.

Can anyone suggest an alternative way of accessing and returning the status parameter who's value will be an XML Document from the context without using Context.Request.Unvalidated?

edit

This is not for a webform or MVC project, we have developed a class library whch we ideally want to contain all the payment related features within the assembly, i.e. single responsibility, our front end apps which will be using this do not need to know about the payment side of things.

like image 204
JsonStatham Avatar asked May 16 '14 17:05

JsonStatham


2 Answers

I don't know weither you are using MVC or Web Forms/Web Pages, but there are several solutions available for you. Take a look at this MSDN page for more info about disabling request validation.

Web Forms: add <@ Page validateRequest="false" %> to the top of your page to disable validation for a single page (other options for more pages/parts of an application are in the MSDN page).

MVC: add attribute [ValidateInput(false)] to the top of your action OR add an [AllowHtml] attribute to the property in the model you are binding to.

like image 159
martennis Avatar answered Sep 18 '22 02:09

martennis


You can use BinaryRead and parse the raw request body yourself. See the RawPostValues() method below.

public class Handler1 : IHttpHandler
{
    public bool IsReusable
    {
        get { return false; }
    }

    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/plain";
        context.Response.Write(GetXmlReceiptFromContext(context));
        context.Response.Write("</ br>");
        context.Response.Write(GetXmlReceiptFromContext(context));
    }

    //returns the xml document as string
    private static string GetXmlReceiptFromContext(HttpContext context)
    {
        context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        context.Response.Cache.SetNoStore();
        context.Response.Cache.SetExpires(DateTime.MinValue);
        return RawPostValues(context)
            .SingleOrDefault(kvp => kvp.Key.Equals("status", StringComparison.InvariantCultureIgnoreCase))
            .Value;
    }

    private static IEnumerable<KeyValuePair<string, string>> RawPostValues(HttpContext context)
    {
        if (context.Request.HttpMethod != "POST") yield break;

        var tmpPosition = context.Request.InputStream.Position;
        string[] formElements;

        try
        {
            formElements = System.Text.Encoding.Default.GetString(
                context.Request.BinaryRead(context.Request.ContentLength))
                .Split('&');

            if (formElements.Length < 1) yield break;
        }
        finally
        {
            context.Request.InputStream.Position = tmpPosition;
        }

        foreach (var element in formElements)
        {
            if (string.IsNullOrEmpty(element)) continue;

            var key = element.Substring(0, element.IndexOf('='));
            var value = element.Substring(key.Length + 1, element.Length - key.Length - 1);
            yield return new KeyValuePair<string, string>(key, value);
        }
    }
}

Some quick smoke tests with Fiddler2 revealed that this works. You may have to hammer out some kinks.

Request

POST http://localhost:48707/Handler1.ashx HTTP/1.1
Host: localhost:48707
Content-Length: 19
content-type: application/x-www-form-urlencoded

status=<b>oops!</b>

Response

HTTP/1.1 200 OK
Server: ASP.NET Development Server/11.0.0.0
Date: Thu, 22 May 2014 05:29:26 GMT
X-AspNet-Version: 2.0.50727
Cache-Control: no-cache, no-store
Pragma: no-cache
Expires: -1
Content-Type: text/plain; charset=utf-8
Content-Length: 12
Connection: Close

<b>oops!</b>
like image 26
Scott Goodman Avatar answered Sep 18 '22 02:09

Scott Goodman