Tag Archives: WCF

Resolving the dreaded System.ServiceModel.AddressAccessDeniedException error

I had a complex WCF service based solution working on my development PC but due to a problem when installing Windows 8.1 I had to ‘Refresh’ my PC which basically means reinstalling Windows, losing all my applications, but not my documents or data. So I had a few days of sorting out Windows, reinstalling apps and trying to get all my settings back to just the way they were before.

Now that I’ve reinstalled Visual Studio 2012 my project no longer functions correctly. When I debug a unit test the WCF Service Host displays an error:

Please try changing the HTTP port to 8733 or running as Administrator.
System.ServiceModel.AddressAccessDeniedException: HTTP could not register URL http://+:8732/Design_Time_Addresses/MyWCFService/Name/. Your process does not have access rights to this namespace (see http://go.microsoft.com/fwlink/?LinkId=70353 for details). —> System.Net.HttpListenerException: Access is denied

Apparently the usual solution to this is to run Visual Studio as administrator. However I’m unable to do that as the architecture we use at work requires us to reference DLLs on a network drive and network drives cannot be accessed when you run a program as administrator (aka elevated).

The other alternative of changing the port to 8733 would require editing every service, re-referencing them and then rebuilding the solution and hoping that it works (unlikely).

After a bit of digging around and research I found out that recent versions of Windows enforce security settings that prevent you from listening to any ports. I’m assuming that when Visual Studio is installed it reserves a port for it’s own use so that you can host and thus debug web services. This was the localhost:8732 port on my development machine but with reinstalling Visual studio it is now localhost:8733, unfortunately all my app.config files in the solution point to port 8732.

However this can be fixed!

Run an elevated command prompt and execute ‘netsh http show urlacl’. This displays the list of reserved ports amongst which I found this:

Reserved URL            : http://+:8733/Design_Time_Addresses/
User: NT AUTHORITY\INTERACTIVE

Which, I’m assuming, is the entry added when Visual Studio was installed.

Executing the following command reserves the 8732 url/port:

‘netsh http add urlacl url=http://+:8732/ user=WORK\Robin’

Restart Visual Studio and all of a sudden my solution works again.

Which endpoint is actually being used?

Private Function GetEndpointAddress(name As String) As String
Debug.Print("--- GetEndpointAddress ---")
Dim address As String = "Unknown"
Dim appConfig As Configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)
Debug.Print("app.config: " & appConfig.FilePath)
Dim serviceModel As ServiceModelSectionGroup = ServiceModelSectionGroup.GetSectionGroup(appConfig)
Dim bindings As BindingsSection = serviceModel.Bindings
Dim endpoints As ChannelEndpointElementCollection = serviceModel.Client.Endpoints
For i As Integer = 0 To endpoints.Count - 1
Dim endpoint As ChannelEndpointElement = endpoints(i)
Debug.Print("Endpoint: " & endpoint.Name & " - " & endpoint.Address.ToString)
If endpoint.Name = name Then
address = endpoint.Address.ToString
End If
Next
Debug.Print("--- GetEndpointAddress ---")
Return address
End Function

An interesting way to get around the limitations of a Using block when calling WCF Services

As you may have already experienced there are potential problems with a Using block when interacting with a WCF Service. For example this code can easily produce an undecipherable WCF CommunicationObjectFaultedException  error for no apparent reason:

Using service As New WCF_ServiceReference.MessageClient
'This is the 'payload' code block:
For Each item As Message In MessageList
If service.SendMessage(item) = True Then
MessageList.Remove(item)
End If
Next
End Using

After some research you will discover that the Microsoft recommendation is to wrap the ‘payload’ code in a Try…Catch block instead of a Using block. See ‘Expected Exceptions’ (http://msdn.microsoft.com/en-us/library/aa354510.aspx) for details. This results in the rather longwinded code below:

Dim service As New WCF_ServiceReference.MessageClient
'Exceptions that are thrown from communication methods on a Windows Communication Foundation (WCF) client are either expected or unexpected.
Try
'Here is the 'payload' code block again
For Each item As Message In MessageList
If service.SendMessage(item) = True Then
MessageList.Remove(item)
End If
Next
service.Close()
Catch timex As TimeoutException
'Expected exceptions from communication methods on a WCF client include TimeoutException, CommunicationException, and any derived class of CommunicationException. These indicate a problem during communication that can be safely handled by aborting the WCF client and reporting a communication failure. Because external factors can cause these errors in any application, correct applications must catch these exceptions and recover when they occur.
service.Abort()
Catch commex As CommunicationException
'Code that calls a client communication method must catch the TimeoutException and CommunicationException. One way to handle such errors is to abort the client and report the communication failure.
service.Abort()
Catch ex As Exception
'Typically there is no useful way to handle unexpected errors, so typically you should not catch them when calling a WCF client communication method.
'Throw
Finally
service.Dispose()
End Try

However there is another way to implement this in a manner much more similar to a Using block:

ServiceHelper.Using(Of WCF_ServiceReference.MessageClient)(
Sub(service)
'Here is the 'payload' code block again
For Each item As Message In MessageList 'Note that MessageList is in scope because it is part of the containing class
If service.SendMessage(item) = True Then
MessageList.Remove(item)
End If
Next
End Sub)

This method relies on a ServiceHelper class with a Using function:

Public Shared Sub [Using](Of ServiceT As {ICommunicationObject, IDisposable, New})(action As Action(Of ServiceT))
Dim service = New ServiceT()
Dim serviceclosed As Boolean = False
Try
action(service)
If service.State <> CommunicationState.Faulted Then
service.Close()
serviceclosed = True
End If
Finally
If serviceclosed = False Then
service.Abort()
End If
End Try
End Sub

The using function takes a generic parameter that matches the interfaces supported by a WCF service and an anonymous subroutine (aka lambda). What this means in practice is that we call ServiceHelper.Using passing a WCF service type and a subroutine that consists of the code inside the original Using block. The Using function executes the procedure and, crucially, handles any faulted errors, calling close or abort as required. This has the advantages of being considerably fewer lines of code then in the original procedure, handles errors gracefully, and can be debugged easily.

Note that the code inside the anonymous procedure must not call service.Close or service.Abort as these are handled by the Using procedure.

The only problem with the ServiceHelper class is that we can only pass a subroutine and not a function. So going further we can overload the Using procedure by adding another procedure to our ServiceHelper class to allow for a function that returns a result:

Public Shared Function [Using](Of ServiceT As {ICommunicationObject, IDisposable, New}, TResult)(action As Func(Of ServiceT, TResult)) As TResult
Dim service = New ServiceT()
Dim serviceclosed As Boolean = False
Dim result As TResult
Try
result = action(service)
If service.State <> CommunicationState.Faulted Then
service.Close()
serviceclosed = True
End If
Finally
If serviceclosed = False Then
service.Abort()
End If
End Try
Return result
End Function

Which can be used like this:

Dim result As Boolean = ServiceHelper.Using(Of WCF_ServiceReference.MessageClient, Boolean)(
Function(service) As Boolean
'Here is the 'payload' code block again
For Each item As Message In MessageList 'Note that MessageList is in scope because it is part of the containing class
If service.SendMessage(item) = True Then
MessageList.Remove(item)
End If
Next
Return True
End Function)

Naturally you can carry on adding other Using procedures with different signatures to account for all the variations of the  Action and Func delegates  that are available but the simplest solution is to add a single input parameter, which can take an object of any type, and use that to pass in any required data. This gives us two more procedures to round out our ServiceHelper class:

Public Shared Sub [Using](Of ServiceT As {ICommunicationObject, IDisposable, New}, TParameter)(input As TParameter, action As Action(Of ServiceT, TParameter))
Dim service = New ServiceT()
Dim serviceclosed As Boolean = False
Try
action(service, input)
If service.State <> CommunicationState.Faulted Then
service.Close()
serviceclosed = True
End If
Finally
If serviceclosed = False Then
service.Abort()
End If
End Try
End Sub

Public Shared Function [Using](Of ServiceT As {ICommunicationObject, IDisposable, New}, TParameter, TResult)(input As TParameter, action As Func(Of ServiceT, TParameter, TResult)) As TResult
Dim service = New ServiceT()
Dim serviceclosed As Boolean = False
Dim result As TResult
Try
result = action(service, input)
If service.State <> CommunicationState.Faulted Then
service.Close()
serviceclosed = True
End If
Finally
If serviceclosed = False Then
service.Abort()
End If
End Try
Return result
End Function

Which are used like this:

Dim messages As New List(Of Message)
ServiceHelper.Using(Of WCF_ServiceReference.MessageClient, List(Of Message))(messages,
Sub(service, msglist)
'Here is the 'payload' code block again
For Each item As Message In msglist 'Note that we pass in the message list as a parameter and thus do not rely on the containing class's property
If service.SendMessage(item) = True Then
MessageList.Remove(item)
End If
Next
End Sub)

Dim messages As New List(Of Message)
Dim result As Boolean = ServiceHelper.Using(Of WCF_ServiceReference.MessageClient, List(Of Message), Boolean)(messages,
Function(service, msglist) As Boolean
'Here is the 'payload' code block again
For Each item As Message In msglist 'Note that we pass in the message list as a parameter and thus do not rely on the containing class's property
If service.SendMessage(item) = True Then
MessageList.Remove(item)
End If
Next
Return True
End Function)