• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 21068
  • Last Modified:

C# code to add a custom HTTP Header

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
phadley
Asked:
phadley
  • 10
  • 9
  • 7
  • +1
1 Solution
 
sachiekCommented:
http://www.codeproject.com/csharp/HTTPeep.asp
You can use to utlity to test your response headers.


Sachi
0
 
phadleyAuthor Commented:
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
 
sachiekCommented:
What is that kind of output you are geting from your above code? Is it in null?


Sachi
0
Technology Partners: 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!

 
phadleyAuthor Commented:
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
 
sachiekCommented:
When you are doing it - it should be added well before page is rendered.

Try it in Page init method.


Sachi
0
 
sachiekCommented:
There is anotherway to send custom headers. Check this article.

http://www.codeproject.com/csharp/HttpWebRequest_Response.asp
0
 
neil_richardsCommented:
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
 
neil_richardsCommented:
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
 
sachiekCommented:
Hi Neil,
  Headers can be added surely.


Sachi
0
 
neil_richardsCommented:
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
 
sachiekCommented:
I guess he is trying to write to response header .


Sachi
0
 
neil_richardsCommented:
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
 
phadleyAuthor Commented:
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
 
phadleyAuthor Commented:
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
 
neil_richardsCommented:
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
 
phadleyAuthor Commented:
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
 
phadleyAuthor Commented:
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
 
neil_richardsCommented:
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
 
phadleyAuthor Commented:
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
 
neil_richardsCommented:
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
 
phadleyAuthor Commented:
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
 
phadleyAuthor Commented:
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
 
neil_richardsCommented:
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
 
neil_richardsCommented:
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
 
raghav9992003Commented:
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

Receive 1:1 tech help

Solve your biggest tech problems alongside global tech experts with 1:1 help.

  • 10
  • 9
  • 7
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now