HOWTO: Fix WCF Host Name on IIS

This is a problem I have tripped across before, and it just popped up again.  Time for a post on how to fix it, mainly so I won’t have to track down MSDN articles and obscure posts to remember how to do it!

When building a WCF Web Service on your local machine, the service will automatically generate WSDL for you with an address similar to http://YOURPC/MyService.svc.  This works fine when testing locally, but when you want to publish this to your production environment so it can be used by World + Dog, it doesn’t respect the fact you have a nice URL you would like to use instead.  For example, if your production server is “Server01″ and the URL you have assigned to the website in IIS is my.publicserver.com, your service may look like this:
WCF Service, wrong URL

Instead of displaying the “real” URL (my.publicserver.com), it displays the name of the server (server01) instead. Not at all what is required! Worse still, connections to your web server will fail because the WSDL is pointing to the non-published server name and your client won’t be able to get there.  This is because WCF automatically uses the IIS Site Bindings to determine what the base addresses for the service should be.

The solution is to update the IIS metabase so IIS knows what to do with the request, then WCF will pick up on this. To fix this, perform the following steps.

Get the Website Identifier from IIS

To change the site bindings you need to know which site to change.  Open the IIS Manager to view the sites available, find the one you want to change, and record the website id in the “Identifier” column.  You will need this in the next step.
IIS Manager

Change the IIS Site Bindings
The format of an IIS site binding is “<ip>:<port>:<hostname>”. For HTTP, the default site binding for the default web site is “:80:”. The service gets messages from any IP addresses for the host and it uses “weak” wildcard for address registration. It needs to be the same as the same host name for the site so that it shows up in your service base address. The IIS utility tool adsutil.vbs (or appcmd.exe on IIS7) is used to modify the IIS metabase entries.
View your current site bindings using the example below.

NOTE – YOU MUST USE YOUR WEBSITE IDENTIFIER.

cscript.exe //NoLogo %systemdrive%\inetpub\adminscripts\adsutil.vbs get W3SVC/your_website_identifier_here/ServerBindings

and, for SSL/secure connections, use the following to view the current site bindings:

cscript.exe //NoLogo %systemdrive%\inetpub\adminscripts\adsutil.vbs get W3SVC/your_website_identifier_here/SecureBindings

To change the site bindings, modify the “get” to a “set” and put in your domain name to link to as per the following example:

cscript.exe //nologo %systemdrive%\inetpub\adminscripts\adsutil.vbs set W3SVC/your_website_identifier_here/ServerBindings “:80:my.publicserver.com”

For HTTPS:

cscript.exe //nologo %systemdrive%\inetpub\adminscripts\adsutil.vbs set W3SVC/your_website_identifier_here/SecureBindings “:443:my.publicserver.com”

Reset the App Pool
When the IIS settings have been changed, WCF will not automatically pick up the changes from the IIS Metabase until the AppDomain has been restarted. Do this via:

  • Changing/resaving the web.config file for the virtual application (you don’t need to actually change the file, as long as it is saved so .NET picks up the change and restarts the app domain)
  • Run “iisreset.exe”
  • Restart the server

All Fixed!
This should complete the changes. When you query the WCF service again, the base address should be correct.

WCF Service, Right URL

About these ads

33 Responses to “HOWTO: Fix WCF Host Name on IIS”

  1. uquandux Says:

    Thanks a lot, this manual was just right the thing I needed to get it working. :) Thanks!

  2. Scott Lotus Says:

    Hi,

    I have followed the method about several times but cannot access my service.scv page anymore.

    Amended meta data for 80 and 443
    Tried domain.com and https://domain.com
    Corerct site ID was used
    IIS reset
    Restarted server

    Any ideas ?

    Scott

  3. Scott Lotus Says:

    sorry , update to the above. the service stopped because when i run

    cscript.exe //nologo %systemdrive%\inetpub\adminscripts\adsutil.vbs set W3SVC/your_website_identifier_here/SecureBindings “:443:my.publicserver.com”

    the IP under WEBSITE / ADVANCED for the SSL socket changes to 255.255.255.255

    When i delete this entry (wont let me amend) and enter the correct IP the site starts but the

    svcutil.exe https://localhost/Service.svc?wsdl

    shows local host still :(

  4. Imran Says:

    This is very nice artical but can you explain how to handle similar problem with ID address instead to Domain Name.
    I’ve deployed my WCF to server1 and having IP Address xxx.xxx.xxx.xxx. This service works perfect when i access it with machine name but fails in case of IP address.

  5. gavinmckay Says:

    Hi Imran,

    I’m sure you have a good reason, but why would you want to access via an IP address instead of a host/machine name? If you only use an IP address you can get caught up if the IP address is dynamically assigned (in which case it may change and your service won’t work).

    Anyway, I haven’t tried the same trick with an ip address instead of a service name, but in theory you should just be able to replace “my.publicserver.com” with the IP address you want to use.

    HTH

    Gavin.

  6. Imran Says:

    Hi, Gavin
    In fact, we have a server on particular IP and we have only available way is to depend on IP only.
    Thanks for tip my problem has been resolved by your help.
    Regads,
    Imran

  7. MikeC Says:

    Hi, Gavin thanks for the info. However, this won’t work on a shared host, unless your ISP allows it. Is there a WCF configuration that would fix this? As a configuration manager, I would rather this be set in the web.config some how, as opposed to the IIS Site configuration. For portability, it’s simpler to use the web.config.

    Thanks.

    • gavinmckay Says:

      Hi Craig,

      I’m not sure how possible this would be, but you might be able to create your own IMetadataExchange interface that could be implemented by WCF when providing WSDL information.
      Considering that it is possible to publish your own metadata via code, you might also be able to create your own IMetadataExchange class that WCF could then instantiate and provide to the consumer.

      Either that, or you can just turn off mex and provide a fixed WSDL file instead. You can use the svcutil wcf utility to accomplish that, and just change the url to be the correct one you want. Probably a lot simpler than creating your own IMetadataExchange.

      Regards,

      Gavin.

  8. slilmigualo Says:

    OMG enjoyed reading this post. I submitted your rss to my reader.

  9. Sandeep Says:

    I have tried to follow the solution provided.

    When the binding is changed to http://www.mydomain.in the URL mydomain.in stops working.

    When setting the binding to mydomain.in, http://www.mydomain.in no longer works.

    We can change the binding but it will cause one of the URL to break.

    • gavinmckay Says:

      Hi Sandeep,

      So you want to bind two URLs to the same instance? Not sure if this can be done. I don’t know of any way to specify multiple urls in an IIS binding. Because you are specifying a contract, the contract is linked within IIS to the URL you provide. If you have the choice, link it to http://www.mydomain.in because it will work better for applications that use port 80 and expect HTTP as the protocol.

      One possible workaround could be to create another website within IIS on a separate IP Address, and point it to the same directory. So you would have two websites in IIS, one for http://www.mydomain.in and the other for mydomain.in. You could then bind these to the appropriate URL. You would need to change your DNS setup probably so http://www.mydomain.in and mydomain.in point to the different IP addresses. It’s possible you could achieve the same thing with a router as well, but that’s far more technical on a routing level. a Network Engineer would be required for the routing work.

      For example:

      192.168.1.10 -> http://www.mydomain.in -> c:\inetpub\wwwroot\mywcfapplication
      192.168.1.11 -> mydomain.in -> c:\inetpub\wwwroot\mywcfapplication

      With appropriate router configuration, it would be possible to have one external ip address a.b.c.d point to a router, then have the router push traffic to the appropriate site based on the url requested. Again, you would need a Network Engineer to configure this for you.

      You would definitely need to have two websites for this to work however as IIS wants to bind to a name in order to resolve addresses properly.

  10. Ger Says:

    You can also use the metabase explorer (which is in IIS6 resource kit) to make the changes.
    Go to IIS and write down the identifier.

    Then open the metabase explorer and go to W3SVC, lookup the site using the identifier key and change the Multistring binding 443 to something like
    :443:www.mywebsite.com.

    Close the metabase explorer and run IISReset.

    You’re good to go!

    • gavinmckay Says:

      Great tip, thanks, I’ll add that to the list! Considering the format is the same, I am assuming either method updates exactly the same information… that would make sense anyway.

  11. Matt Says:

    Hey there,

    Have you gone through this for WinServer2k8? Is it the same process? Also, I’d be interested in learning about the IP method, as well — we run a lot of WCF services on our LAN and there’s a lot of manual DNS config that has to happen in order to deploy them. Would be nice if the services could just use their IP addresses instead of a hostname.

    Thanks!

    • gavinmckay Says:

      Hi Matt,

      Unfortunately no, I haven’t tried this on Win2K8. It’s on my list of things to do lol

      I don’t see how the process would change however. Even though IIS7 is part of Win2K8, the http.sys component that does the heavy lifting should be the same? This is pure guess-work though, I’ll run it through on a Win2K8 box and report back.

      RE the IP method, it is exactly the same as the host-name method except you substitute the IP address for the name of your host in the instructions. According to another poster, that does work. Is this what you mean? I assume so you can use https://1.2.3.4/myservice instead of http://myserver.domain.local/myservice?

      • Matt Says:

        Yep, that’s right. We basically want to have our VMWare installation auto-spool up service instances (Win2k8 VMs) when needed, and we want to just use the IP addresses instead of having to specify service1, service2, etc., in DNS

      • gavinmckay Says:

        OK, then substituting the IP address for the hostname should definitely work then. Under the hood you are providing a mapping via http.sys so that IIS can pass on the requested web service address http://1.2.3.4/my.service/ and bind it correctly via WCF, then your code should take over from there.

        The challenge of course is just managing the IP addresses so you can remember what each ip is linked to which service :)

  12. Xaria Says:

    I am not able to make this work.
    How does your web.config look like? Do you include a Host tag in web.config for your website or you include the host tag under app.config for WCF?
    I am asuuming you host tag will be something like this

    • gavinmckay Says:

      Hi – I’m sorry but your web.config didn’t come through. Are you able to re-post it?

      The host name does not appear in the web.config for the service. WCF configuration uses the system.serviceModel section of web.config, but the endpoint element is only for the last portion of the url to bind with. I’ll add a new post to illustrate an example web.config, that may help.

      EDIT: New post added with a sample system.serviceModel section, might be of use to you?

  13. Omar Says:

    Great post!, but no need for restart using ws 2008 r2 :D even better! :D

    Thanks!

  14. Brendan. Says:

    Hi, I’m having this problem also – I am too trying to use an IP we have a dev server here on a fixed IP before things get uploaded to the prod srv with domain.

    First off I had to strip out the quotations from the SET command line above as this resulted in a hostheader that consisted of one double quoute: ”

    :80:my.publicserver.com worked fine but “:80:my.publicserver.com” stopped the website from running.

    Once I finally got my host header in as the IP the website would run but even a helloworld.htm test page would come back with a “Bad Request (Invalid Hostname)” error, any ideas??

    • gavinmckay Says:

      Hi Brendan,

      What are your current IIS bindings? If you use the “get” version of the command above, what does it report back to you? You might have a conflict in your bindings.

      Also if it is not returning helloworld.htm, that may point to other problems. Request helloworld.htm is not using WCF at all, just plain old vanilla IIS.

      Gavin.

      • chandangarg02@Gmail.com Says:

        I also got the same error same as brendon.. Can you please tell what is the problem?

  15. Internet solutions team Says:

    Excellent article, it helped us….thanks…We had the same issue… while publishing wcf service hosted on IIS 7 windows 2008 server.

    • dev Says:

      what is the command you use for IIS 7, I have been searching for a while on how to get this to work. thanks.

      • gavinmckay Says:

        Hello – the IIS7 command should be exactly the same… are you getting an error when you try the command?

  16. scott_lotus Says:

    Add the following to WEB.CONFIG and ensure your 80 host header is defined worked for me using WCF .net 4.0 on IIS6.

    No need to amend adsutil.vb.

    Hope that helps someone.
    Scott

    ——————————-
    example
    ——————————-
    serviceBehaviors
    behavior name=””>
    useRequestHeadersForMetadataAddress>
    defaultPorts>
    add scheme=”http” port=”80″ />
    add scheme=”https” port=”443″ />
    /defaultPorts>
    /useRequestHeadersForMetadataAddress>
    /behavior>
    /serviceBehaviors>
    ——————————-

  17. Core Says:

    It’s a very useful article. Perfect! It was all I need

  18. Changing the publicly exposed endpoint URL for a WCF web service without changing the site bindings | PHP Developer Resource Says:

    [...] know that I can fix this by changing the bindings of the site in IIS as per HOWTO: Fix WCF Host Name on IIS however in this case the site is shared with another application which stops working if I do this [...]

  19. Infomax Says:

    Please follow this hotfix:
    http://support.microsoft.com/kb/971842

    All you need is this tag in web.config

    <behavior name="”>

  20. TotPe.Ro Says:

    this is the solution http://stackoverflow.com/a/9671430

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Follow

Get every new post delivered to your Inbox.

%d bloggers like this: