tags:

views:

84

answers:

1

I am trying to access http://localhost/tempservicehost/tempservice.svc and I am getting the following error:

Error Description: 'Resource does not exist'

This may be because an invalid URI or HTTP method was specified. Please see the service help page for constructing valid requests to the service.

The funny thing is that http://localhost/tempservicehost/tempservice.svc/help is working fine. Not only that, all my endpoints are working fine.

I am using IIS 7.5 (Win 2008 R2). Application developed using .NET 4.0

Post Updated (following is the code):

<ServiceContract()>
Public Interface ITestSvc

    <OperationContract()>
    <Description("")>
    <WebInvoke(Bodystyle:=WebMessageBodyStyle.Bare,
               Method:="POST",
               UriTemplate:="GetCodes")>
    Function GetCodes(ByVal oReq As ReqGetCodes) As RespGetCodes


End Interface

Public Class TestSvc
    Implements ITestSvc

    Public Function GetCodes(ByVal oReq As ReqGetCodes) As RespGetCodes Implements ITestSvc.GetCodes
        Dim o As New RespGetCodes
        Dim lstGetCodes = New List(Of ClassGetCodes) From {
            New ClassGetCodes With {.App_Code = "a1", .SystemFlag = True},
            New ClassGetCodes With {.App_Code = "a2", .SystemFlag = False},
            New ClassGetCodes With {.App_Code = "a3", .SystemFlag = True},
            New ClassGetCodes With {.App_Code = "a4", .SystemFlag = True},
            New ClassGetCodes With {.App_Code = "a5", .SystemFlag = False}
            }
        o.GetCodesArray = lstGetCodes.ToArray
        Return o
    End Function

End Class

Public Class TestWebHttpBehavior
    Inherits WebHttpBehavior

    Protected Overrides Sub AddServerErrorHandlers(ByVal endpoint As System.ServiceModel.Description.ServiceEndpoint, ByVal endpointDispatcher As System.ServiceModel.Dispatcher.EndpointDispatcher)
        endpointDispatcher.ChannelDispatcher.ErrorHandlers.Clear()
        endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add(New TestErrorHandler)
    End Sub

End Class

Public Class TestWcfSvcHostFactory
    Inherits ServiceHostFactory

    Protected Overrides Function CreateServiceHost(ByVal serviceType As Type, ByVal baseAddresses As Uri()) As ServiceHost
        Dim result As New WebServiceHost2(serviceType, True, baseAddresses)
        Dim sEnableBasicAuth As String = System.Configuration.ConfigurationManager.AppSettings.Get("EnableBasicAuthentication")
        If String.IsNullOrEmpty(sEnableBasicAuth) OrElse String.Compare(sEnableBasicAuth, "false", True) <> 0 Then
            result.Interceptors.Add(New TestRequestInterceptor(System.Web.Security.Membership.Provider, "Personify Authentication"))
        End If
        result.Authorization.PrincipalPermissionMode = PrincipalPermissionMode.None
        Dim bahavior As New TestWebHttpBehavior With {.AutomaticFormatSelectionEnabled = True}
        result.Description.Endpoints(0).Behaviors.Add(bahavior)
        Return result
    End Function

End Class

Public Class TestRequestInterceptor
    Inherits RequestInterceptor
    Private m_provider As MembershipProvider
    Private m_realm As String

    Public Sub New(ByVal provider As MembershipProvider, ByVal realm As String)
        MyBase.New(False)
        Me.m_provider = provider
        Me.m_realm = realm
    End Sub

    Protected ReadOnly Property Realm() As String
        Get
            Return m_realm
        End Get
    End Property

    Protected ReadOnly Property Provider() As MembershipProvider
        Get
            Return m_provider
        End Get
    End Property

    Public Overrides Sub ProcessRequest(ByRef requestContext As RequestContext)
        Dim credentials As String() = ExtractCredentials(requestContext.RequestMessage)
        If credentials.Length > 0 AndAlso AuthenticateUser(credentials(0), credentials(1)) Then
            InitializeSecurityContext(requestContext.RequestMessage, credentials(0))
        Else
            Dim reply As Message = Message.CreateMessage(MessageVersion.None, Nothing)
            Dim responseProperty As New HttpResponseMessageProperty() With {.StatusCode = HttpStatusCode.Unauthorized}
            responseProperty.Headers.Add("WWW-Authenticate", String.Format("Basic realm=""{0}""", Realm))

            reply.Properties(HttpResponseMessageProperty.Name) = responseProperty
            requestContext.Reply(reply)

            requestContext = Nothing
        End If
    End Sub

    Private Function AuthenticateUser(ByVal username As String, ByVal password As String) As Boolean
        If Provider.ValidateUser(username, password) Then
            Return True
        End If

        Return False
    End Function

    Private Function ExtractCredentials(ByVal requestMessage As Message) As String()
        Dim request As HttpRequestMessageProperty = DirectCast(requestMessage.Properties(HttpRequestMessageProperty.Name), HttpRequestMessageProperty)

        Dim authHeader As String = request.Headers("Authorization")

        If authHeader IsNot Nothing AndAlso authHeader.StartsWith("Basic") Then
            Dim encodedUserPass As String = authHeader.Substring(6).Trim()

            Dim encoding__1 As Encoding = Encoding.GetEncoding("iso-8859-1")
            Dim userPass As String = encoding__1.GetString(Convert.FromBase64String(encodedUserPass))
            Dim separator As Integer = userPass.IndexOf(":"c)

            Dim credentials As String() = New String(1) {}
            credentials(0) = userPass.Substring(0, separator)
            credentials(1) = userPass.Substring(separator + 1)

            Return credentials
        End If

        Return New String() {}
    End Function

    Private Sub InitializeSecurityContext(ByVal request As Message, ByVal username As String)
        Dim principal As New GenericPrincipal(New GenericIdentity(username), New String() {})

        Dim policies As New List(Of IAuthorizationPolicy)()
        policies.Add(New PrincipalAuthorizationPolicy(principal))
        Dim securityContext As New ServiceSecurityContext(policies.AsReadOnly())

        If request.Properties.Security IsNot Nothing Then
            request.Properties.Security.ServiceSecurityContext = securityContext
        Else
            request.Properties.Security = New SecurityMessageProperty() With { _
             .ServiceSecurityContext = securityContext _
            }
        End If
    End Sub

    Private Class PrincipalAuthorizationPolicy
        Implements IAuthorizationPolicy

        Private m_id As String = Guid.NewGuid().ToString()
        Private user As IPrincipal

        Public Sub New(ByVal user As IPrincipal)
            Me.user = user
        End Sub

        Public ReadOnly Property Id As String Implements System.IdentityModel.Policy.IAuthorizationComponent.Id
            Get
                Return Me.m_id
            End Get
        End Property

        Public Function Evaluate(ByVal evaluationContext As System.IdentityModel.Policy.EvaluationContext, ByRef state As Object) As Boolean Implements System.IdentityModel.Policy.IAuthorizationPolicy.Evaluate
            evaluationContext.AddClaimSet(Me, New DefaultClaimSet(Claim.CreateNameClaim(user.Identity.Name)))
            evaluationContext.Properties("Identities") = New List(Of IIdentity)(New IIdentity() {user.Identity})
            evaluationContext.Properties("Principal") = user
            Return True
        End Function

        Public ReadOnly Property Issuer As System.IdentityModel.Claims.ClaimSet Implements System.IdentityModel.Policy.IAuthorizationPolicy.Issuer
            Get
                Return ClaimSet.System
            End Get
        End Property
    End Class

End Class

The config is here:

 <system.serviceModel>
    <services>
      <service behaviorConfiguration="TestWcfServiceBehavior"
        name="TestServiceLib.TestSvc">
        <endpoint address="" binding="webHttpBinding" behaviorConfiguration="EPrestBehavior"
          name="EPrest" contract="TestServiceLib.ITestSvc" />
        <endpoint address="mex" binding="mexHttpBinding" name="EPmex"
          contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior name="EPrestBehavior">
          <webHttp />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="TestWcfServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
+1  A: 

I Had a similar issue,

I found that if i navigated to an actual resource it was fine.

for example

http://localhost/tempservicehost/tempservice.svc/test/

assuming you have the following method as well

[OperationContract]    
[WebGet(UriTemplate = "/test/")]
public Test TestMethod()
{
  return new Test("Hello world");
}

what has happened here is that the standard 404 error that is normally returned has not been rendered the way you are expecting it to. (usually you get a blue header and a line saying service end point or similar)

If you want to customise your errors there is a question http://stackoverflow.com/q/3835665/81044 That explains how to pick up error codes on the way through and modify the return.

Bluephlame
I too found that. But, I could not get rid of the error. Let me know, if you find any solution for the above.
The error in that case is a legitimate error. It is a 404 Not Found (which is true as there is not a resource at tempservice,svc) The question should now be how do you customize the error.
Bluephlame
But, if I remove custom http behavior and custom host factory, I don't experience that error!
Yeah you do, it's just rendered nicely. when you remove your custom host and behavior and track the request using fiddler, watch the HTTP response code it will be 404.
Bluephlame
check out this Question here to customise the error http://stackoverflow.com/q/3835665/81044
Bluephlame