【问题标题】:WCF REST deployment Error: "Resource Does not exist"WCF REST 部署错误:“资源不存在”
【发布时间】:2011-04-11 21:15:37
【问题描述】:

我正在尝试访问 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>

【问题讨论】:

  • 您可以添加您的服务合同(代码为您的操作定义 WebGet 和 WebInvoke 属性)吗?
  • 帖子更新了整个代码。如果您需要更多代码,请告诉我。

标签: wcf wcf-rest


【解决方案1】:

我有类似的问题,

我发现如果我导航到一个实际的资源就很好了。

例如

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 这解释了如何在通过过程中获取错误代码并修改返回。

【讨论】:

  • 我也发现了。但是,我无法摆脱错误。如果您找到上述任何解决方案,请告诉我。
  • 这种情况下的错误是合法错误。这是一个 404 Not Found(这是真的,因为 tempservice,svc 上没有资源)现在的问题应该是如何自定义错误。
  • 但是,如果我删除自定义 http 行为和自定义主机工厂,我不会遇到该错误!
  • 是的,它只是渲染得很好。当您删除自定义主机和行为并使用 fiddler 跟踪请求时,请注意 HTTP 响应代码,它将是 404。
  • 在此处查看此问题以自定义错误stackoverflow.com/q/3835665/81044
猜你喜欢
  • 2021-06-16
  • 1970-01-01
  • 2019-06-26
  • 1970-01-01
  • 2021-05-21
  • 2017-09-06
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多