Deploy webservice to remote intranet

GrahamJ

New member
Joined
Mar 25, 2014
Messages
1
Programming Experience
10+
Hello all. I'm just getting back into vb.net after a few years out developing php and vis fox apps so a little rusty.
I have a Windows CE based barcode scanner which will update stock levels held in SQL Server 2008 on the main file server.

My thinking is the scanner will have a Winforms application and use a webservice to fetch data and send the stock updates back.

I'm just trying to get my head round where the webservice will live and how to call it. My SBS test server is called CSLServer1, I reckon I can see the project will add a reference to CSLServer1/cslscanner etc.

The client's server is called Server1, it looks like I'll just need to copy the files from my Inetpub\wwwroot to their Inetpub\wwwroot.

The reference is confusing me though, does this mean I would have to go out on site, connect to their network and add a reference to the project to Server1/cslscanner?

I can't see any way to make the reference to the webservice dynamic based on my test server or the live server.

Appreciate any pointers.
Regards
Graham
 
You can host a WCF service inside IIS, but it is tricky to debug. I find it much easier to host it inside a Windows service. Here is an example of the code required. This is a Windows service that hosts my SaasAdminWcfService over a plain text WSHttp endpoint on port 8164. I can build it, install it locally, add a reference to it in my client application to test and debug. On final deployment you can just install the windows service on the server, or install it through IIS, and then just update your client project reference.

Service host:

Imports System.ServiceProcess
Imports System.ServiceModel.Description
Imports System.Net

Public Class SaasAdminWcfServiceHost
    Inherits ServiceBase

    Private WithEvents svcHost As ServiceHost

    Public Sub New()
        ServiceName = "SaasAdminWcfService"
        CanHandlePowerEvent = False
        CanHandleSessionChangeEvent = False
        CanPauseAndContinue = False
        CanShutdown = False
        CanStop = True
        AutoLog = True
    End Sub

    Public Shared Sub Main()
        ServiceBase.Run(New SaasAdminWcfServiceHost())
    End Sub

    Protected Overrides Sub OnStart(ByVal args() As String)
        If svcHost IsNot Nothing Then
            svcHost.Close()
        End If

        svcHost = New ServiceHost(GetType(SaasAdminWcfService), New Uri("http://" & GetIPv4Address() & ":8164"))
        svcHost.Description.Behaviors.Add(New ServiceMetadataBehavior())
        svcHost.AddServiceEndpoint(GetType(SaasAdminWcfService), New WSHttpBinding(SecurityMode.None, False), "SaasAdminWcfService")
        svcHost.AddServiceEndpoint(GetType(IMetadataExchange), New WSHttpBinding(SecurityMode.None, False), "mex")

        Dim debugBehavior As ServiceDebugBehavior = svcHost.Description.Behaviors.Find(Of ServiceDebugBehavior)()
        If debugBehavior Is Nothing Then
            svcHost.Description.Behaviors.Add(New ServiceDebugBehavior() With {.IncludeExceptionDetailInFaults = True})
        Else
            debugBehavior.IncludeExceptionDetailInFaults = True
        End If

        Try
            svcHost.Open()
        Catch ex As Exception
            svcHost.Abort()
        End Try

    End Sub

    Protected Overrides Sub OnStop()
        If svcHost IsNot Nothing Then
            svcHost.Close()
            svcHost = Nothing
        End If
    End Sub

    Private Function GetIPv4Address() As String
        Dim ipAddress = Dns.GetHostEntry(Dns.GetHostName).AddressList.FirstOrDefault(Function(x) x.AddressFamily = Sockets.AddressFamily.InterNetwork)

        Return If(ipAddress Is Nothing, "localhost", ipAddress.ToString)
    End Function


End Class


Service installer, so the Windows service can install with installutil.exe:

Imports System.Configuration.Install
Imports System.ComponentModel
Imports System.ServiceProcess

<RunInstaller(True)> _
Public Class SaasAdminWcfServiceInstaller
    Inherits Installer

    Public Sub New()
        Using p As New ServiceProcessInstaller()
            p.Account = ServiceAccount.User
            Using s As New ServiceInstaller()
                s.ServiceName = "SaasAdminWcfService"
                s.Description = "SaaS WCF Remote Admin Service"
                s.DisplayName = "SaaS WCF Remote Admin Service"
                s.StartType = ServiceStartMode.Automatic
                s.DelayedAutoStart = True
                Me.Installers.Add(p)
                Me.Installers.Add(s)
            End Using
        End Using
    End Sub
End Class
 
By the way the service reference is stored in the app.config file, you can just edit the URI. If the service changes though you have to update the reference for VS to rebuild its client code and recompile. Another benefit of this method is that you avoid having to use impersonation through IIS to secure your resources. You can just create an active directory user with permissions tailored to what your service needs, and host the service under that user. Also the above is unsecured, normally you would use some certificate security and a https endpoint, and also disable the ServiceDebugBehavior and metadata endpoint to avoid disclosing sensitive information.
 
Last edited:
On the topic of hosting and referencing WCF services, here is a little gem:

Imports System.ServiceModel

Public Class ServiceReferenceFactory(Of T)

    Public Function GetServiceInstance(ByVal address As String, ByVal binding As Channels.Binding) As T
        Dim endpoint As New EndpointAddress(address)
        Return ChannelFactory(Of T).CreateChannel(binding, endpoint)
    End Function


End Class


It allows you to create service references at run-time, although you have to create your client interfaces beforehand with svcutil.exe. To use, run svcutil.exe to generate the client interface code, include it in your project, and use it with the above class like this:

Dim svcRef = New ServiceReferenceFactory(Of ISaasAdminWcfService).GetServiceInstance("http://someuri.com/myservice:8164", New WSHttpBinding(SecurityMode.None, False))
 
Back
Top