Skip to content
avatar

Simulating HttpContext with Sessions and POSTs for ASP.NET

Here’s a little something I’ve been hacking together at work, so that we can do some unit testing on my current project. It’s largely based on this post by Phil Haack, but adds support for using Sessions (by assigning to the Session property) and doing Http POSTs as well as GETs, both of which are necessary for our tests, and were requested in the comments on Phil’s post.

As you can see, the Session support is bare-bones at the moment, because what’s there satisfies my needs for now. If you wander outside just stashing stuff in the session, you’ll get a handy exception to tell you that you’ve surpassed what the code can currently do.

Hope it helps you!

namespace ElectronicFieldBook.Tests
{
    /// <summary>
    /// Allows us to set the HTTP context with a valid simulated request
    /// From <http://haacked.com/archive/2005/06/11/Simulating_HttpContext.aspx>
    /// </summary>
    public static class WebRequestSimulator
    {
        public class WithoutSession
        {
            public static HttpContext Get()
            {
                return Get("localhost", "", string.Empty);
            }

        <span class="kwrd">public</span> <span class="kwrd">static</span> HttpContext Get(<span class="kwrd">string</span> host, <span class="kwrd">string</span> page, <span class="kwrd">string</span> query)
        {
            SimulatedHttpRequest req = <span class="kwrd">new</span> SimulatedHttpRequest(<span class="str">"GET"</span>, host, page, query);
            <span class="kwrd">return</span> HttpContext.Current = <span class="kwrd">new</span> HttpContext(req);
        }

        <span class="kwrd">public</span> <span class="kwrd">static</span> HttpContext Post(<span class="kwrd">string</span> host, <span class="kwrd">string</span> page, <span class="kwrd">string</span> query, <span class="kwrd">string</span> body)
        {
            SimulatedHttpRequest req = <span class="kwrd">new</span> SimulatedHttpRequest(<span class="str">"POST"</span>, host, page, query);
            req.Body = body;
            <span class="kwrd">return</span> HttpContext.Current = <span class="kwrd">new</span> HttpContext(req);
        }
    }

    <span class="kwrd">public</span> <span class="kwrd">static</span> HttpContext Get()
    {
        <span class="kwrd">return</span> AddSessionState(WithoutSession.Get());
    }

    <span class="kwrd">public</span> <span class="kwrd">static</span> HttpContext Get(<span class="kwrd">string</span> host, <span class="kwrd">string</span> page, <span class="kwrd">string</span> query)
    {
        <span class="kwrd">return</span> AddSessionState(WithoutSession.Get(host, page, query));
    }

    <span class="kwrd">public</span> <span class="kwrd">static</span> HttpContext Post(<span class="kwrd">string</span> host, <span class="kwrd">string</span> page, <span class="kwrd">string</span> query, <span class="kwrd">string</span> body)
    {
        <span class="kwrd">return</span> AddSessionState(WithoutSession.Post(host, page, query, body));
    }

    <span class="kwrd">public</span> <span class="kwrd">static</span> HttpContext AddSessionState(HttpContext context)
    {
        IHttpSessionState ssn = Session;
        <span class="kwrd">if</span> (ssn != <span class="kwrd">null</span>)
        {
            SessionStateUtility.AddHttpSessionStateToContext(context, ssn);
        }
        <span class="kwrd">return</span> context;
    }

    <span class="kwrd">private</span> <span class="kwrd">static</span> IHttpSessionState session;
    <span class="kwrd">public</span> <span class="kwrd">static</span> IHttpSessionState Session
    {
        get { <span class="kwrd">return</span> session; }
        set { session = <span class="kwrd">value</span>; }
    }

    <span class="rem">/// &lt;summary&gt;</span>
    <span class="rem">/// Used to simulate an HttpRequest.</span>
    <span class="rem">/// &lt;/summary&gt;</span>
    <span class="kwrd">public</span> <span class="kwrd">class</span> SimulatedHttpRequest : SimpleWorkerRequest
    {
        <span class="kwrd">private</span> <span class="kwrd">string</span> verb;
        <span class="kwrd">private</span> <span class="kwrd">string</span> host;
        <span class="kwrd">private</span> <span class="kwrd">string</span> body = <span class="kwrd">string</span>.Empty;
        <span class="kwrd">public</span> <span class="kwrd">string</span> Body { get { <span class="kwrd">return</span> body; } set { body = <span class="kwrd">value</span>; } }

        <span class="kwrd">public</span> SimulatedHttpRequest(
            <span class="kwrd">string</span> verb,
            <span class="kwrd">string</span> host,
            <span class="kwrd">string</span> page,
            <span class="kwrd">string</span> query)
            : <span class="kwrd">this</span>(<span class="str">"/"</span>, AppDomain.CurrentDomain.BaseDirectory, verb, host, page, query, <span class="kwrd">null</span>)
        { }

        <span class="kwrd">public</span> SimulatedHttpRequest(
            <span class="kwrd">string</span> appVirtualDir,
            <span class="kwrd">string</span> appPhysicalDir,
            <span class="kwrd">string</span> verb,
            <span class="kwrd">string</span> host,
            <span class="kwrd">string</span> page,
            <span class="kwrd">string</span> query,
            TextWriter output)
            : <span class="kwrd">base</span>(appVirtualDir, appPhysicalDir, page, query, output)
        {
            <span class="kwrd">if</span> (<span class="kwrd">string</span>.IsNullOrEmpty(verb))
                <span class="kwrd">throw</span> <span class="kwrd">new</span> ArgumentNullException(<span class="str">"verb"</span>, <span class="str">"Verb cannot be null nor empty."</span>);
            <span class="kwrd">if</span> (<span class="kwrd">string</span>.IsNullOrEmpty(host))
                <span class="kwrd">throw</span> <span class="kwrd">new</span> ArgumentNullException(<span class="str">"host"</span>, <span class="str">"Host cannot be null nor empty."</span>);

            <span class="kwrd">this</span>.verb = verb;
            <span class="kwrd">this</span>.host = host;
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Gets the name of the server.</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="rem">/// &lt;returns&gt;&lt;/returns&gt;</span>
        <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">string</span> GetServerName()
        {
            <span class="kwrd">return</span> host;
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Maps the path to a filesystem path.</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="rem">/// &lt;param name="virtualPath"&gt;Virtual path.&lt;/param&gt;</span>
        <span class="rem">/// &lt;returns&gt;&lt;/returns&gt;</span>
        <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">string</span> MapPath(<span class="kwrd">string</span> virtualPath)
        {
            <span class="kwrd">return</span> Path.Combine(<span class="kwrd">this</span>.GetAppPath(), virtualPath);
        }

        <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">string</span> GetHttpVerbName()
        {
            <span class="kwrd">return</span> verb;
        }

        <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">byte</span>[] GetPreloadedEntityBody()
        {
            <span class="kwrd">return</span> <span class="kwrd">new</span> UTF8Encoding().GetBytes(Body);
        }

        <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">int</span> GetPreloadedEntityBodyLength()
        {
            <span class="kwrd">return</span> GetPreloadedEntityBody().Length;
        }

        <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">string</span> GetKnownRequestHeader(<span class="kwrd">int</span> index)
        {
            <span class="kwrd">bool</span> isPost = verb == <span class="str">"POST"</span>;
            <span class="kwrd">if</span> (!isPost) <span class="kwrd">return</span> <span class="kwrd">base</span>.GetKnownRequestHeader(index);

            <span class="kwrd">if</span> (index == HeaderContentType)
            {
                <span class="kwrd">return</span> <span class="str">"application/x-www-form-urlencoded; charset=utf-8"</span>;
            }
            <span class="kwrd">else</span> <span class="kwrd">if</span> (index == HeaderContentLength)
            {
                <span class="kwrd">return</span> GetPreloadedEntityBodyLength().ToString();
            }

            <span class="kwrd">return</span> <span class="kwrd">base</span>.GetKnownRequestHeader(index);
        }
    }

    <span class="kwrd">public</span> <span class="kwrd">class</span> SimulatedHttpSessionState : IHttpSessionState
    {
        <span class="kwrd">private</span> IDictionary objects = <span class="kwrd">new</span> Dictionary&lt;<span class="kwrd">object</span>, <span class="kwrd">object</span>&gt;();

        <span class="kwrd">private</span> <span class="kwrd">bool</span> isAbandoned = <span class="kwrd">false</span>;
        <span class="kwrd">public</span> <span class="kwrd">bool</span> IsAbandoned
        {
            get { <span class="kwrd">return</span> isAbandoned; }
            set { isAbandoned = <span class="kwrd">value</span>; }
        }

        <span class="kwrd">public</span> <span class="kwrd">void</span> Add(<span class="kwrd">string</span> name, <span class="kwrd">object</span> <span class="kwrd">value</span>)
        {
            objects.Remove(name);
            objects.Add(name, <span class="kwrd">value</span>);
        }

        <span class="kwrd">public</span> <span class="kwrd">void</span> Clear()
        {
            objects.Clear();
        }

        <span class="kwrd">public</span> <span class="kwrd">int</span> Count
        {
            get { <span class="kwrd">return</span> objects.Count; }
        }

        <span class="kwrd">public</span> System.Collections.IEnumerator GetEnumerator()
        {
            <span class="kwrd">return</span> objects.Values.GetEnumerator();
        }

        <span class="kwrd">public</span> <span class="kwrd">void</span> Remove(<span class="kwrd">string</span> name)
        {
            objects.Remove(name);
        }

        <span class="kwrd">public</span> <span class="kwrd">void</span> RemoveAll()
        {
            Clear();
        }

        <span class="kwrd">public</span> <span class="kwrd">void</span> RemoveAt(<span class="kwrd">int</span> index)
        {
            <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"The method or operation is not implemented."</span>);
        }

        <span class="kwrd">public</span> <span class="kwrd">object</span> <span class="kwrd">this</span>[<span class="kwrd">int</span> index]
        {
            get
            {
                <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"The method or operation is not implemented."</span>);
            }
            set
            {
                <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"The method or operation is not implemented."</span>);
            }
        }

        <span class="kwrd">public</span> <span class="kwrd">object</span> <span class="kwrd">this</span>[<span class="kwrd">string</span> name]
        {
            get
            {
                <span class="kwrd">return</span> objects[name];
            }
            set
            {
                Add(name, <span class="kwrd">value</span>);
            }
        }

        <span class="kwrd">public</span> <span class="kwrd">void</span> Abandon()
        {
            isAbandoned = <span class="kwrd">true</span>;
        }

        <span class="kwrd">public</span> <span class="kwrd">int</span> CodePage
        {
            get
            {
                <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"The method or operation is not implemented."</span>);
            }
            set
            {
                <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"The method or operation is not implemented."</span>);
            }
        }

        <span class="kwrd">public</span> HttpCookieMode CookieMode
        {
            get { <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"The method or operation is not implemented."</span>); }
        }

        <span class="kwrd">public</span> <span class="kwrd">void</span> CopyTo(Array array, <span class="kwrd">int</span> index)
        {
            <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"The method or operation is not implemented."</span>);
        }

        <span class="kwrd">public</span> <span class="kwrd">bool</span> IsCookieless
        {
            get { <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"The method or operation is not implemented."</span>); }
        }

        <span class="kwrd">public</span> <span class="kwrd">bool</span> IsNewSession
        {
            get { <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"The method or operation is not implemented."</span>); }
        }

        <span class="kwrd">public</span> <span class="kwrd">bool</span> IsReadOnly
        {
            get { <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"The method or operation is not implemented."</span>); }
        }

        <span class="kwrd">public</span> <span class="kwrd">bool</span> IsSynchronized
        {
            get { <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"The method or operation is not implemented."</span>); }
        }

        <span class="kwrd">public</span> System.Collections.Specialized.NameObjectCollectionBase.KeysCollection Keys
        {
            get { <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"The method or operation is not implemented."</span>); }
        }

        <span class="kwrd">public</span> <span class="kwrd">int</span> LCID
        {
            get
            {
                <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"The method or operation is not implemented."</span>);
            }
            set
            {
                <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"The method or operation is not implemented."</span>);
            }
        }

        <span class="kwrd">public</span> SessionStateMode Mode
        {
            get { <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"The method or operation is not implemented."</span>); }
        }

        <span class="kwrd">public</span> <span class="kwrd">string</span> SessionID
        {
            get { <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"The method or operation is not implemented."</span>); }
        }

        <span class="kwrd">public</span> HttpStaticObjectsCollection StaticObjects
        {
            get { <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"The method or operation is not implemented."</span>); }
        }

        <span class="kwrd">public</span> <span class="kwrd">object</span> SyncRoot
        {
            get { <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"The method or operation is not implemented."</span>); }
        }

        <span class="kwrd">public</span> <span class="kwrd">int</span> Timeout
        {
            get
            {
                <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"The method or operation is not implemented."</span>);
            }
            set
            {
                <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"The method or operation is not implemented."</span>);
            }
        }
    }
}

}

{ 2 } Comments

  1. avatar Haacked | 2007-05-3 at 12:38 am | Permalink

    I’ve made a bunch of improvements to mine. May I include your session support code? I wasn’t aware of anyone else interested in this code, but if there are others, might want to make this another CodePlex project.

  2. avatar TALlama | 2007-05-4 at 6:11 pm | Permalink

    Feel free to steal whatever you want; that’s why I posted it here. ;)