?
Solved

C# code to add a custom HTTP Header

Posted on 2005-04-04
27
Medium Priority
?
20,383 Views
Last Modified: 2009-07-06
I have read about using the Response.AddHeader( "name", "value" ) method to add a custom HTTP Header, but I can't get it to work!

Here's my test code that doesn't work:

// addHTTPHeader.aspx
<%@ Page Language="C#" AutoEventWireup="true" %>
<html>
  <head>
    <script runat="server">
      void AddHeaders(Object sender, EventArgs e)
      {
        Response.AddHeader( "EMPLOYEEID", "1" );
      }
    </script>
  </head>
  <body>
    <asp:hyperlink Text="Submit" OnClick="AddHeaders" runat="server" NavigateUrl="dumpHeaders.aspx"></asp:hyperlink>
  </body>
</html>


// dumpHeaders.aspx
<%@ Page Language="C#" AutoEventWireup="true" %>
<html>
  <head>
    <script runat="server">
      void Page_Load(Object sender, EventArgs e)
      {
        // print header vars to screen:
        Response.Write("<br>Header vars: ");
        NameValueCollection headerVariables = Request.Headers;
        String[] headerKeys = headerVariables.AllKeys;
        Response.Write(((0 == headerKeys.Length) ? "(none)" : "" + headerKeys.Length) + "<br>");
        for( int i=0; i<headerKeys.Length; ++i )
        {
          Response.Write( headerKeys[i] + " = '" + headerVariables[ headerKeys[i] ] + "'<br>" );
        }
      }
    </script>
  </head>
  <body>
  </body>
</html>
0
Comment
Question by:phadley
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 10
  • 9
  • 7
  • +1
27 Comments
 
LVL 11

Expert Comment

by:sachiek
ID: 13704592
http://www.codeproject.com/csharp/HTTPeep.asp
You can use to utlity to test your response headers.


Sachi
0
 
LVL 1

Author Comment

by:phadley
ID: 13704732
Yes, that's a pretty sweet little utility.  However, testing the response header is not the problem. <b>Sending</b> the response header is the problem.  For 500 pts, you're going to have to help me fix the code I provided.
0
 
LVL 11

Expert Comment

by:sachiek
ID: 13704763
What is that kind of output you are geting from your above code? Is it in null?


Sachi
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 1

Author Comment

by:phadley
ID: 13704797
The problem is, I'm not seeing the EMPLOYEEID header that I added.  I added it to the Response of the addHTTPHeader.aspx page.  It should have appeared on the dumpHeaders.aspx page, but didn't.
0
 
LVL 11

Expert Comment

by:sachiek
ID: 13704814
When you are doing it - it should be added well before page is rendered.

Try it in Page init method.


Sachi
0
 
LVL 11

Expert Comment

by:sachiek
ID: 13704815
There is anotherway to send custom headers. Check this article.

http://www.codeproject.com/csharp/HttpWebRequest_Response.asp
0
 
LVL 2

Expert Comment

by:neil_richards
ID: 13704989
Can I ask why you're trying to put the employeeID in the response header?  Normally, you would pass it in a query string or in a form post.  If you wanted the ID shared throughout the application you could also use session variables.  

Anyways, the reason it isn't executing is that onclick is a javascript event for a hyperlink and not a server-side event.  

<form runat="server">
      <asp:LinkButton id="LinkButton1" runat="server" OnClick="AddHeaders">LinkButton</asp:LinkButton>
</form>

That executes your AddHeaders code.  However, you would need to execute the redirect within the AddHeaders function calling

Server.Transfer("dumpHeaders.aspx")
0
 
LVL 2

Expert Comment

by:neil_richards
ID: 13705181
Having thought about this a little more, what you're specifically trying to do does not make sense within the ASP.NET framework.  

Your code writes a header to the response object, and then creates a new request to a different page.  Now, in your dumpHeaders page, you're trying to read the headers of the request object.  That request is totally unique to the response object you're writing to.  In fact there is no way to read the headers of a Response object, only addHeaders.

Similarly, you can't add headers to the HttpRequest object as HttpRequest.Headers is readonly.  

Where does this get you?  Well if you want to write a header in addHTTPHeader there is no way for it to appear at the same time as in dumpHeaders.  What you can do is create a variable, and add it to the request, and then add a header within dumpHeaders.  
0
 
LVL 11

Expert Comment

by:sachiek
ID: 13705207
Hi Neil,
  Headers can be added surely.


Sachi
0
 
LVL 2

Expert Comment

by:neil_richards
ID: 13705283
They can be added to the response, not the request using the HttpRequest and HttpResponse objects

Request.Headers.Add( "EMPLOYEEID", "1" );

generates the following exception: System.NotSupportedException: Collection is read-only.

Further

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebhttprequestclassheaderstopic.asp

defines the HttpRequest.Headers object accordingly

[Visual Basic]
Public ReadOnly Property Headers As NameValueCollection
[C#]
public NameValueCollection Headers {get;}
[C++]
public: __property NameValueCollection* get_Headers();
[JScript]
public function get Headers() : NameValueCollection;

The flow of what phadley is trying to do doesn't make sense.  He (guessing) is trying to write to the response object, redirect to a new page and then read the value he added to the response header from the request, which is impossible.  Additionally, there is no clear way of reading the HttpResponse headers you've already written.  I'd be happy to be proven wrong, but I can't see how.
0
 
LVL 11

Expert Comment

by:sachiek
ID: 13705301
I guess he is trying to write to response header .


Sachi
0
 
LVL 2

Expert Comment

by:neil_richards
ID: 13705499
That's not really the point.  In order to help phadley we need to know what his/her goal is.  Just posting a Response header is easy, and phadley had that from the start.  phadley's problem was 1 - it wasn't firing the AddHeaders event (to which I have proposed a solution) and 2, phadley couldn't see employeeID within the dumpHeaders page (which is not possible based on his approach).  Until phadley clarify's their requirements, it's hard to know how to solve the problem.  

Perhaps the problem is as simple as trying to fire the AddHeaders event properly, but I doubt it.  In any case, I'm content to get more feedback from phadley to find out exactly what they're trying to achieve.
0
 
LVL 1

Author Comment

by:phadley
ID: 13708805
I'm trying to write a pair of ASPX pages that pass a value in the HTTP Header.  The first page would write the value to the HTTP Header, and the second would read it in from the HTTP Header.

I agree that using Session vars would be a better solution, but in this case I have no choice as to the design because I need to integrate my web application with an existing (unchangable) application that passes a custom var in the HTTP Header.

neil_richards,

I took your suggestion to change the asp:hyperlink to an asp:linkbutton, but the EMPLOYEEID header still fails to appear in the dumpHeaders.aspx page.  Here is the new code and output:

// addHTTPHeader.aspx
<%@ Page Language="C#" AutoEventWireup="true" %>
<html>
  <head>
    <script runat="server">
      void AddHeaders(Object sender, EventArgs e)
      {
        Response.AddHeader( "EMPLOYEEID", "1" );
        Server.Transfer("dumpHeaders.aspx");
      }
    </script>
  </head>
  <body>
    <form runat="server">
      <asp:LinkButton Text="Submit" OnClick="AddHeaders" runat="server"></asp:LinkButton>
    </form>
  </body>
</html>

// dumpHeaders.aspx
<%@ Page Language="C#" AutoEventWireup="true" %>
<html>
  <head>
    <script runat="server">
      void Page_Load(Object sender, EventArgs e)
      {
        // print header vars to screen:
        Response.Write("<b>Header vars: ");
        NameValueCollection headerVariables = Request.Headers;
        String[] headerKeys = headerVariables.AllKeys;
        Response.Write(((0 == headerKeys.Length) ? "(none)" : "" + headerKeys.Length) + "</b><br>");
        for( int i=0; i<headerKeys.Length; ++i )
        {
          Response.Write( "<b>" + i + ":</b> " + headerKeys[i] + " = '" + headerVariables[ headerKeys[i] ] + "'<br>" );
        }
      }
    </script>
  </head>
  <body>
  </body>
</html>

// output from dumpHeaders.aspx
Header vars: 10
0: Cache-Control = 'no-cache'
1: Connection = 'Keep-Alive'
2: Content-Length = '97'
3: Content-Type = 'application/x-www-form-urlencoded'
4: Accept = 'image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*'
5: Accept-Encoding = 'gzip, deflate'
6: Accept-Language = 'en-us'
7: Host = 'localhost'
8: User-Agent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)'
9: Weferer = 'QZUIVOTQNQEMSFDULHPQQWOYIYZUNNYCGPKYLEJGDGVCJVTLB'
0
 
LVL 1

Author Comment

by:phadley
ID: 13709005
Sachi's article above suggests that the System.Net.HttpWebRequest is the class needed to add custom HTTP Headers.  However, the examples contained therein are not web pages.  What I want is a web page that will add dynamic HTTP Header values based on what a user types into a field.  This is what I'm trying to accomplish with the addHTTPHeader.aspx page.

I think I have made my intentions clear now.
0
 
LVL 2

Expert Comment

by:neil_richards
ID: 13709632
I'm very sorry, but your present approach is not possible:

When you are posting to Response in your AddHeaders function, you are posting to the object that ASP.NET is preparing to send down to the browser.  You can't then turn around and expect to read that object as the request in your next page.  Requests go from Browser to WebServer and Responses go from Server to Browser.  You want to go Server to Server.  Unfortunately, while ASP.NET lets you do this (using Server.Transfer), it does not let you modify the HttpRequest headers as they are readonly (as I demonstrated above).  Most other HttpRequest collections (form, querystring) are also read only.  

In this case you must use the HttpWebRequest and HttpWebResponse classes as Sachi suggests.  For these objects, the Headers collection is accessible.  It's not really very easy, but it's the only way to accomplish what you're looking for.  

The sample code below should get you started.  You could use this in your AddHeaders method:

      // Create a new 'HttpWebRequest' Object to the mentioned URL.
      HttpWebRequest myHttpWebRequest=(HttpWebRequest)WebRequest.Create("dumpHeaders.aspx");
      myHttpWebRequest.Headers.Add("EmployeeID", "1");

      // Assign the response object of 'HttpWebRequest' to a 'HttpWebResponse' variable.
      HttpWebResponse myHttpWebResponse=(HttpWebResponse)myHttpWebRequest.GetResponse();

      Stream streamResponse=myHttpWebResponse.GetResponseStream();
      StreamReader streamRead = new StreamReader( streamResponse );
      Char[] readBuff = new Char[256];
      int count = streamRead.Read( readBuff, 0, 256 );

      while (count > 0)
      {
          String outputData = new String(readBuff, 0, count);
          Response.Write(outputData);
          count = streamRead.Read(readBuff, 0, 256);
      }
      // Close the Stream object.
      streamResponse.Close();
      streamRead.Close();

      // Release the HttpWebResponse Resource.
      myHttpWebResponse.Close();

Is this clear?  I wish there were a better / easier answer for you, but there doesn't appear to be.  It is a complex operation you're trying to do (at least ASP.NET makes it complex).  Let me know how you get on.  The annoying thing is, if you were using Java, this sort of thing is possible.  

If it were acceptable to pass the value as a non-http header then you could simply append it to the querystring (ie. dumpheaders.aspx?employeeID=1) or possibly set it to the value of a form variable (see http://www.developer.com/net/asp/article.php/3299641)

Anyways, that's a lot to chew over, let me know which bits require clarification.

0
 
LVL 1

Author Comment

by:phadley
ID: 13709737
neil_richards,

I'll try adding your code to my AddHeaders method, and see if it works.  But, what do you make of this:

http://www.asp.net/Default.aspx?tabindex=9&tabid=48
0
 
LVL 1

Author Comment

by:phadley
ID: 13709834
neil,

I used your code for the implementation of the AddHeaders method, and a strange thing happened.  Upon reloading the addHTTPHeader.aspx file, I received the following output:

Header vars: 2
0: Host = 'localhost'
1: EMPLOYEEID = '1'

   Submit

It appears that the AddHeaders method was executed even before I clicked the Submit button.  The EMPLOYEEID header was added, but it wasn't supposed to appear until I clicked Submit and go to the dumpHeaders.aspx page.

Any ideas?
0
 
LVL 2

Expert Comment

by:neil_richards
ID: 13712147
Re: the url you passed along.  It pretty much reiterates what I was saying, although it suggests saving your values in Cookies (which is pretty much like using session variables).

Could you repost your addHTTPHeader.aspx based on the changes you've made?  That will give me a better idea of what's happening.  If you changed the dumpHeaders.aspx then repost that too please.

0
 
LVL 1

Author Comment

by:phadley
ID: 13712999
Here's the current code and output.  Notice that the output is for addHTTPHeader.aspx, not dumpHeaders.aspx.  What I'd really like is to be able to submit header values that are input by the user on the addHTTPHeader.aspx page, and then appear on the dumpHeaders.aspx page.

//addHTTPHeader.aspx
<%@ Page Language="C#" AutoEventWireup="true" %>
<%@ import Namespace="System.Net" %>
<%@ import Namespace="System.IO" %>
<html>
  <head>
    <script runat="server">
      string employeeID = null;
      void Page_Load(Object sender, EventArgs e)
      {
        // Create a new 'HttpWebRequest' Object to the mentioned URL.
        HttpWebRequest myHttpWebRequest=(HttpWebRequest)WebRequest.Create("http://localhost/reimbursement/dumpHeaders.aspx");
        myHttpWebRequest.Headers.Add("EMPLOYEEID", "1");
                  
        // Assign the response object of 'HttpWebRequest' to a 'HttpWebResponse' variable.
        HttpWebResponse myHttpWebResponse=(HttpWebResponse)myHttpWebRequest.GetResponse();
            
        Stream streamResponse=myHttpWebResponse.GetResponseStream();
        StreamReader streamRead = new StreamReader( streamResponse );
        Response.Write( streamRead.ReadToEnd() );

        // Close the Stream object.
        streamResponse.Close();
        streamRead.Close();
            
        // Release the HttpWebResponse Resource.
        myHttpWebResponse.Close();
        employeeID = Request.ServerVariables["HTTP_EMPLOYEEID"];
      }
    </script>
  </head>
  <body>
    employeeID = '<% Response.Write((null == employeeID) ? "null" : employeeID); %>'
  </body>
</html>

//dumpHeaders.aspx
<%@ Page Language="C#" AutoEventWireup="true" %>
<html>
  <head>
    <script runat="server">
      void Page_Load(Object sender, EventArgs e)
      {
        // print header vars to screen:
        Response.Write("<b>Header vars: ");
        NameValueCollection headerVariables = Request.Headers;
        String[] headerKeys = headerVariables.AllKeys;
        Response.Write(((0 == headerKeys.Length) ? "(none)" : "" + headerKeys.Length) + "</b><br>");
        for( int i=0; i<headerKeys.Length; ++i )
        {
          Response.Write( "<b>" + i + ":</b> " + headerKeys[i] + " = '" + headerVariables[ headerKeys[i] ] + "'<br>" );
        }
      }
    </script>
  </head>
  <body>
  </body>
</html>

//output from addHTTPHeader.aspx:
Header vars: 2
0: Host = 'localhost'
1: EMPLOYEEID = '1'
employeeID = 'null'

0
 
LVL 2

Accepted Solution

by:
neil_richards earned 2000 total points
ID: 13714433
Re: "It appears that the AddHeaders method was executed even before I clicked the Submit button. ".  You're using the page_load function now, so it's going to run whenever the page loads.

What I've given you below are three files, two are almost identical to your old ones, I've just renamed them so you can keep your old files.

AddHeaders.aspx is equivalent to addHTTPHeader.aspx.  It's purpose is to gather the details as you tried to do in the first instance.  It creates a HttpWebRequest, which is passes to a proxy class, because, as we discussed, it is not possible to modify the Request object in the way that you want.

HeaderProxy.aspx simply takes the request from AddHeaders and passes it to ReceiveHeaders.aspx.  Upon completion, it receives the response and dumps it to screen.  The reason for doing this is because it will allow ReceiveHeaders to act as though it were receiving a proper request, which should allow for integration into your old application.

ReceiveHeaders.aspx is your dumpHeaders.aspx file, untouched.  

//AddHeaders.aspx
<%@ Page Language="C#" AutoEventWireup="true" %>
<%@ import Namespace="System.Net" %>

<HTML>
      <HEAD>
            <script runat="server">
      string employeeID = null;
      void AddHeaders(Object sender, EventArgs e)
      {
                  // Create a new 'HttpWebRequest' Object to the mentioned URL.
                  HttpWebRequest myHttpWebRequest=(HttpWebRequest)WebRequest.Create("http://localhost/HeaderProxy/ReceiveHeader.aspx");
                  myHttpWebRequest.Headers.Add("EMPLOYEEID", "1");
                  
                  Session.Add("proxyRequest", myHttpWebRequest);
                  Server.Transfer("HeaderProxy.aspx");
      }
            </script>
      </HEAD>
      <body>
            <form runat="server">
                  <asp:LinkButton id="LinkButton1" runat="server" OnClick="AddHeaders">LinkButton</asp:LinkButton>
            </form>
      </body>
</HTML>

//HeaderProxy.aspx
<%@ Page Language="C#" AutoEventWireup="true" %>
<%@ import Namespace="System.Net" %>
<%@ import Namespace="System.IO" %>
<HTML>
      <HEAD>
            <script runat="server">
            void Page_Load(Object sender, EventArgs e)
            {
                        HttpWebRequest myHttpWebRequest = (HttpWebRequest)Session["proxyRequest"];
                        
                        // Assign the response object of 'HttpWebRequest' to a 'HttpWebResponse' variable.
                        HttpWebResponse myHttpWebResponse=(HttpWebResponse)myHttpWebRequest.GetResponse();
                     
                        Stream streamResponse=myHttpWebResponse.GetResponseStream();
                        StreamReader streamRead = new StreamReader( streamResponse );
                        Response.Write( streamRead.ReadToEnd() );

                        // Close the Stream object.
                        streamResponse.Close();
                        streamRead.Close();
                     
                        // Release the HttpWebResponse Resource.
                        myHttpWebResponse.Close();
            }
            </script>
      </HEAD>
      <body>
      </body>
</HTML>

//ReceiveHeader.aspx
<%@ Page Language="C#" AutoEventWireup="true" %>
<html>
  <head>
    <script runat="server">
      void Page_Load(Object sender, EventArgs e)
      {
        // print header vars to screen:
        Response.Write("<br>Header vars: ");
        NameValueCollection headerVariables = Request.Headers;
        String[] headerKeys = headerVariables.AllKeys;
        Response.Write(((0 == headerKeys.Length) ? "(none)" : "" + headerKeys.Length) + "<br>");
        for( int i=0; i<headerKeys.Length; ++i )
        {
          Response.Write( headerKeys[i] + " = '" + headerVariables[ headerKeys[i] ] + "'<br>" );
        }
      }
    </script>
  </head>
  <body>
  </body>
</html>
0
 
LVL 1

Author Comment

by:phadley
ID: 13723249
Neil,

Great, this seems to work.  The ReceiveHeader.aspx page is receiving the EMPLOYEEID header!

Now comes the *real* problem: if I store the EMPLOYEEID value in a Session variable, the value disappears when I go to another page (see the output below for NextPage.aspx).  I have modified your code very slightly, and added a new, NextPage.aspx file.  I'll also include my web.config, since it applies here.

Thanks for your help so far, Neil.  You have earned the 500 pts for part one.  I'm upping the points to 800 for this second part of the question.  I hope you can help me with this second part, but if you don't, I'll split the points accordingly.

// AddHeaders.aspx
<%@ Page Language="C#" AutoEventWireup="true" %>
<%@ import Namespace="System.Net" %>
<HTML>
  <HEAD>
    <script runat="server">
      string employeeID = null;
      void Page_Load(Object sender, EventArgs e)
      {
        // Create a new 'HttpWebRequest' Object to the mentioned URL.
        HttpWebRequest myHttpWebRequest=(HttpWebRequest)WebRequest.Create("http://localhost/reimbursement/ReceiveHeader.aspx");
        myHttpWebRequest.Headers.Add("EMPLOYEEID", "1");
                        
        Session["proxyRequest"] = myHttpWebRequest;
        Server.Transfer("HeaderProxy.aspx");
      }
    </script>
  </HEAD>
  <body>
  </body>
</HTML>

// HeaderProxy.aspx
(no change)

// ReceiveHeader.aspx
<%@ Page Language="C#" AutoEventWireup="true" %>
<html>
  <head>
    <script runat="server">
      void Page_Load(Object sender, EventArgs e)
      {
        // receive HTTP_EMPLOYEEID in header:
        string employeeID = Request.ServerVariables["HTTP_EMPLOYEEID"];
        Response.Write("Found header: HTTP_EMPLOYEEID = '" + employeeID + "'");

        // store a Session var for the EMPLOYEEID:
        Response.Write("<br>Setting Session['employeeID'] = '" + employeeID + "'");
        Session["employeeID"] = employeeID;
      }
    </script>
  </head>
  <body>
    <br><a href="NextPage.aspx">Next</a>
  </body>
</html>

// output from ReceiveHeader.aspx
Found header: HTTP_EMPLOYEEID = '1'
Setting Session['employeeID'] = '1'
Next

// NextPage.aspx
<%@ Page Language="C#" AutoEventWireup="true" %>
<html>
  <head>
    <script runat="server">
      void Page_Load(Object sender, EventArgs e)
      {
        Response.Write("Session['employeeID'] is " + ((null == Session["employeeID"]) ? "undefined" : "defined") );
      }
    </script>
  </head>
  <body>
  </body>
</html>

// output from NextPage.aspx:
Session['employeeID'] is undefined

// web.config:
<configuration>
  <system.web>
    <compilation debug="true" />
    <trace enabled="false" localOnly="false" />
    <sessionState mode="InProc" cookieless="false" timeout="20"/>
  </system.web>
</configuration>

- Phil
0
 
LVL 1

Author Comment

by:phadley
ID: 13723275
It seems I can't increase it past 500, but I can credit you another 300 if need be:
http://www.experts-exchange.com/Community_Support/Q_20850037.html
0
 
LVL 2

Expert Comment

by:neil_richards
ID: 13724317
Good stuff, just accept this answer and create a new question pointing to this one....  In the meantime I'll think about the problem
0
 
LVL 2

Expert Comment

by:neil_richards
ID: 13725372
Bleh, getting the sessions to sync up is a massive pain.  Essentially, ASP.NET considers the httpwebrequest to be a different session, no matter how I try to convince it otherwise.  I think I've got a solution which I'll post to the new question after you've created it.  
0
 
LVL 1

Expert Comment

by:raghav9992003
ID: 21622930
Hi phadley,

did u get any solution fro this problem? same is required here.  i desperatly need a solution for this.
if u got then please share with me.
please send it to below ID,
srikanthbdvt@gmail.com
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Lots of people ask this question on how to extend the “MembershipProvider” to make use of custom authentication like using existing database or make use of some other way of authentication. Many blogs show you how to extend the membership provider c…
In .NET 2.0, Microsoft introduced the Web Site.  This was the default way to create a web Project in Visual Studio 2005.  In Visual Studio 2008, the Web Application has been restored as the default web Project in Visual Studio/.NET 3.x The Web Si…
In this brief tutorial Pawel from AdRem Software explains how you can quickly find out which services are running on your network, or what are the IP addresses of servers responsible for each service. Software used is freeware NetCrunch Tools (https…
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …
Suggested Courses

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question