If you need to run multiple sites on the same web server, Host headers is a good choice. The sites will run on the same IP address and can use the same standard ports 80 and 443 without forcing the users to use different port numbers in URL. However, setting up Host headers does take a bit of learning and understanding how the things work.
Server side
In my case, I had an existing site site1.com running on standard ports 80 and 443. I set up another site, site2.com. I wanted site2.com to run on the same ports.
First of all, I didn’t need to touch anything on my current site site1.com. Nothing at all.
With site2.com, I needed to bind it to the same ports but with a distinct Host header. Although I could bind to port 80 via IIS management UI, for port 443 it couldn’t be done. If you are keen to know the reason, it is because of SSL certificate. With IIS UI, you could select different SSL certificates for different Host headers, but, since IIS routes http messages by their Host headers after decoding SSL, all Host headers will always use the same SSL certificate.
So, instead of trying IIS UI, you can easily bind to different Host headers with the following command-line script:
cd %windir%\system32\inetsrv
appcmd set site /site.name:site2 /+bindings.[protocol='https',bindingInformation='*:443:site2.com']
appcmd set site /site.name:site2 /+bindings.[protocol='http',bindingInformation='*:80:site2.com']
appcmd set site /site.name:site2 /+bindings.[protocol='https',bindingInformation='*:443:www.site2.com']
appcmd set site /site.name:site2 /+bindings.[protocol='http',bindingInformation='*:80:www.site2.com']
In the script, I bound site site2 to Host headers site2.com and www.site2.com. I will explain later, in the Client side section, why did I need to bind to 2 names and why I chose these particular names.
You can see all your site binding with this command:
appcmd list sites
SSL certificate
As we’ve said, all sites with different Host headers will use the same SSL certificate. A regular SSL certificate is issued to a single server name. You will need to obtain a more expensive certificate that will work for multiple server names. If you don’t do this, you will get browser’s security warning on mismatching server name in certificate.
Client side
Now we are done with server side. How can the setting be tested?
There is no way how you can ask your browser to attach a Host header to the URL. But you can enter a record into your hosts file, located at %windir%\system32\drivers\etc :
127.0.0.1 site2.com
With this, if you navigate your browser to http://site2.com, your request will arrive to your web server with the Host header correctly set to site2.com.
Finally, you want the whole world to connect to your site without modifying hosts file. You need to do it on your DNS provider. Here you will appreciate the names for the Host headers that we chose above - site2.com and www.site2.com. When you point the domain name site2.com to your server IP address, the DNS provider will automatically set the Host header to site2.com. Likely, you want to access your site also with a www prefix. For this, the DNS provider will set the Host header into www.site2.com. That’s why we needed to bind our site2 in IIS to this header as well.
If you have an ASP.NET Logon control on your page, likely you have noticed that IE8 renders it in a distorted way:
I guess the reason is because the input controls used for the User Name and Password are styled as width:20ex and IE8 treats ex-based width differently for inputs of type “text” and “password”.
There is a simple work-around fixing the problem.
Handle the OnInit event of the Login control like this:
protected void Login1_Init(object sender, EventArgs e)
{
System.Web.UI.WebControls.Login login = sender as System.Web.UI.WebControls.Login;
TextBox txtUserName = login.FindControl("UserName") as TextBox;
TextBox txtPassword = login.FindControl("Password") as TextBox;
txtUserName.CssClass = "FixedLogin";
txtPassword.CssClass = "FixedLogin";
}
and the CSS will be:
.FixedLogin
{
margin-top:1ex;
margin-left:1ex;
width:150px!important;
}
Enjoy the result:

If your web application includes a Reports folder, there is a good chance you will run into this weird problem.
You have some pages in the Reports folder. On your development system everything is fine. You deploy the app on a production or testing server and try navigating to any of the pages in the Reports. The browser greats you with a authentication dialog and you can’t access any of the pages in the Reports.
Check if the server runs SQL Server Reporting Services. If it does, likely you found the culprit. The Reporting Services create their own Reports virtual directory and IIS routes your requests to your Reports folder to the Reporting Services one. The best solution is to rename your Reports to something else, like Reporting. Simple. Works.
This is a common problem in ASP.NET databound controls. I have an ItemTemplate with some html. The html includes data bound parts like this:
<a href='BLOCKED SCRIPTgoView(<%# Eval("Id") %>, <%# Eval("Type") %>)'>View</a>
What I want to achieve is when user clicks the View link, I want to call the javascript function goView and pass to it an integer Id and a string Type like this:
The problem is that my Type field comes from the database as Letter, with no quotes and my javascript call looks like
which results in a javascript error.
Since the href already includes both single and double quotes, it is very hard to add any other quotes, whether with escaping as \”, \’ or not.
An easy way that worked to me was using the second parameter of Eval for formatting. This works:
<a href='BLOCKED SCRIPTgoView(<%# Eval("Id") %>, <%# Eval("Type", "\"{0}\"") %>)'>View</a>
In my first experience with Ajax against WCF Http facade, I needed to pass exceptions from my WCF service back to the browser client. Researching WCF yielded clear understanding that the way of passing exceptions from WCF services to clients is SOAP faults. Numerous examples elaborate using FaultContracts and FaultExceptions. There is only one problem: SOAP faults are not supported in browsers hence have no use in Ajax.
Luckily, there is a very simple way of sending errors to browsers. If you are interested in communicating all exception details, look at this thread: WCF Services with faultexception. I wanted to pass just a single string with error text so I made a much shorter version of the solution offered in the thread:
public class MyService
{ [OperationContract]
public ResponseData<String> MyMethod()
{ ResponseData<String> result = new ResponseData<String>();
try
{ result.Result = GetMyResult();
}
catch (Exception ex)
{ result.ErrorMessage = ex.Message;
}
return result;
}
}
[DataContract]
public class ResponseData<T>
{ private string errorMessage;
[DataMember]
public string ErrorMessage
{ get { return this.errorMessage; } set
{ this.errorMessage = value;
this.IsError = value != null;
}
}
[DataMember]
public bool IsError { get; set; }
[DataMember]
public T Result { get; set; } }
Here is the client-side code:
<script type="text/javascript">
function getMyResult() { MyService.MyMethod(OnSucceeded);
}
function OnSucceeded(result) { if (!result.IsError) { // success
alert(result.Result);
}
else { // error;
alert(result.ErrorMessage);
}
}
</script>
If you have a RadioButtonList control with RepeatLayout=”Flow”, you don’t have any property controlling the spacing between radio button.
For example, this control
<asp:RadioButtonList runat="server" ID="rblSelectOptions" RepeatDirection="Horizontal" RepeatLayout="Flow">
<asp:ListItem Text="Waiting for approval" Value="W" Selected="True" />
<asp:ListItem Text="On hold" Value="H" />
<asp:ListItem Text="All for last 30 days" Value="A" />
<asp:ListItem Text="All" Value="L" />
</asp:RadioButtonList>
will produce this output:
But if you add a CSS rule
<style type="text/css">
#rblSelectOptions_0, #rblSelectOptions_1, #rblSelectOptions_2, #rblSelectOptions_3
{
margin-left:2ex;
}
</style>
The output will be:
Likely, the idea can be improved by using a class CSS selector for list items.
A few useful date calculations:
-- This is quite obvious:
declare @today date = cast(getdate() as date);
-- But this is already not so:
declare @beginningOfWeek date = dateadd(day, 1 - datepart(weekday , @today), @today);
declare @beginningOfNextWeek date = dateadd(week, 1, @beginningOfWeek)
If you want to know the type of the client browser, you will probably check the Request.Browser.Type property. However, you will notice that IE8 is reported as IE7. There is a simple work around for this. If you check the Request.UserAgent property, you will see that IE8 browsers insert word “Trident”. So this code solves the problem:
string browserType = Request.Browser.Type;
// IE8 is not reported in browser type but it can be detected
// by word "Trident" in the user agent
if (Request.UserAgent.ToUpper().Contains("TRIDENT"))
browserType = browserType.Replace("IE7", "IE8");
FTP publishing in VS 2008 is troublesome. Here are 2 hints that may help in avoiding troubles:
1. Don’t publish the same project to multiple sites on the same server. Visual Studio keeps track of published files in an XML document ProjectName.Publish.xml in the project directory. Visual Studio uses the document for deciding what files need to be updated on the server. The published file records are stored in publishTarget elements, one element per server. All files published to the same server will go to the same publishTarget even if they were published to different sites. This will mess up you publishing as Visual Studio will think it has already published the file ignoring the fact that it has published it to a different site.
2. Switching between Passive and Active Mode will have effect only after restarting Visual Studio.
I know a simple and powerful way of moving forward. Move slowly, one step at the time. Big things are made out of many small things.
In this blog I would like to share some small things. They may be useful for you as they have been for me.
Ah, yes, it will be about web programming.