WCF REST部署错误:“资源不存在”

时间:2010-09-13 20:54:52

标签: wcf wcf-rest

我正在尝试访问http://localhost/tempservicehost/tempservice.svc,我收到以下错误:

  

错误说明:'资源没有   存在'

     

这可能是因为无效的URI或   指定了HTTP方法。请参阅   用于构建的服务帮助页面   有效的服务请求。

有趣的是http://localhost/tempservicehost/tempservice.svc/help工作正常。不仅如此,我的所有终端都工作正常。

我正在使用IIS 7.5(Win 2008 R2)。使用.NET 4.0开发的应用程序

发布更新(以下是代码):

<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

配置在这里:

 <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 个答案:

答案 0 :(得分:2)

我有类似的问题,

我发现如果我导航到实际资源就可以了。

例如

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

假设您还有以下方法

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

这里发生的事情是,通常返回的标准404错误没有按照您期望的方式呈现。 (通常你得到一个蓝色的标题和一条说服务终点或类似的行)

如果您想自定义错误,则会出现问题Custom Error Handling message for Custom WebServiceHost 这解释了如何在通过途中获取错误代码并修改返回。