我正在尝试使用WCF进行POST / GET服务。我在哪里遇到没有问题的GET,我的POST服务总是得到错误405.我搜索了这么多帖子,但没有找到让它工作的东西。我现在不知道该尝试什么。
这是我的合同:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Web;
using System.ComponentModel;
namespace DemoService
{
#region Service contract
[ServiceContract]
[ServiceKnownType(typeof(DbElement))]
public interface IDatabaseService
{
#region Services
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "description/{elementID}")]
[Description("Get description of an element, identified in database by its Id")]
DbElement GetElementDescription(string elementId);
[OperationContract]
[WebInvoke(Method = "POST",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "update/description/{Id}")]
[Description("Update description of an element, using its id")]
int UpdateElementName(string Id, DbElement Ident);
#endregion
}
#endregion
#region Service data
[DataContract]
public class DbElement
{
#region Properties
[DataMember(Order = 1)]
public string Name { get; set; }
[DataMember(Order = 0)]
public short SerialNumber { get; set; }
#endregion
internal DbElement()
{
SerialNumber = 0;
Name = string.Empty;
}
}
#endregion
}
我的web.config文件如下所示:
<?xml version="1.0"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
<system.web>
<compilation debug="true"/>
</system.web>
<!-- Following section is to be duplicated in exe app.config file (for the moment) -->
<system.serviceModel>
<services>
<service name="DemoService.DatabaseService" behaviorConfiguration="baseServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8666/1.0"/>
</baseAddresses>
</host>
<endpoint address="REST"
binding="webHttpBinding"
behaviorConfiguration="web"
bindingConfiguration="webHttpBindingConfiguration"
contract="DemoService.IDatabaseService" />
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="webHttpBindingConfiguration" />
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp defaultOutgoingResponseFormat="Json" helpEnabled="true" />
<crossOriginResourceSharingBehavior />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="baseServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="crossOriginResourceSharingBehavior"
type="DemoService.EnableCrossOriginResourceSharingBehavior, DemoService" />
</behaviorExtensions>
</extensions>
</system.serviceModel>
</configuration>
我使用的Cors如下(灵感来自https://enable-cors.org/server_wcf.html)
public class CustomHeaderMessageInspector : IDispatchMessageInspector
{
Dictionary<string, string> requiredHeaders;
public CustomHeaderMessageInspector(Dictionary<string, string> headers)
{
requiredHeaders = headers ?? new Dictionary<string, string>();
}
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
return null;
}
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
var httpHeader = reply.Properties["httpResponse"] as HttpResponseMessageProperty;
foreach (var item in requiredHeaders)
{
httpHeader.Headers.Add(item.Key, item.Value);
}
}
}
public class EnableCrossOriginResourceSharingBehavior : BehaviorExtensionElement, IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
{
var requiredHeaders = new Dictionary<string, string>();
requiredHeaders.Add("Access-Control-Allow-Origin", "*");
requiredHeaders.Add("Access-Control-Request-Methods", "POST,GET,PUT,DELETE,OPTIONS");
requiredHeaders.Add("Access-Control-Allow-Headers", "X-Requested-With,Content-Type");
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new CustomHeaderMessageInspector(requiredHeaders));
}
public void Validate(ServiceEndpoint endpoint)
{
}
public override Type BehaviorType
{
get { return typeof(EnableCrossOriginResourceSharingBehavior); }
}
protected override object CreateBehavior()
{
return new EnableCrossOriginResourceSharingBehavior();
}
}
我的测试客户是
<html></html>
<head>
<script src="jquery.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#jsonp2").click(function() {
$.ajax({
url: "http://localhost:8666/1.0/REST/update/description/2",
data: "SerialNumber=321,Name:hello",
type: "POST",
contentType:"application/json",
crossDomain:true,
headers: { 'Content-Type': 'application/json; charset=UTF-8' },
dataType: "json",
success: function(data) {
alert("Data from Server" + JSON.stringify(data));
},
error: function(jqXHR, textStatus, errorThrown) {
alert("request failed: " + errorThrown);
}
});
});
$("#jsonp3").click(function() {
$.ajax({
url: " http://localhost:8666/1.0/REST/description/2",
type: "GET",
dataType: "json",
success: function(data) {
alert("Data from Server" + JSON.stringify(data));
},
error: function(jqXHR, textStatus, errorThrown) {
alert("request failed: " + errorThrown);
}
});
});
});
</script>
</head>
<body>
<button id="jsonp2" type="button" class="btn btn-info">Send X Post Request</button>
<button id="jsonp3" type="button" class="btn btn-info">Send X Get Request</button>
</body>
</html>
调用GET服务工作得很好。 调用POST服务始终返回代码405而不到达入口点。
Couls有人帮我解决这个问题吗? 谢谢。
PS: 这是来自cient
的请求标头Host :"localhost:8666"
User-Agent :"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0"
Accept :"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
Accept-Language :"fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3"
Accept-Encoding :"gzip, deflate"
Access-Control-Request-Method :"POST"
Access-Control-Request-Headers :"content-type"
Origin :"null"
DNT :"1"
Connection :"keep-alive"
和答案标题:
Access-Control-Allow-Headers :"X-Requested-With,Content-Type"
Access-Control-Allow-Origin :"*"
Access-Control-Request-Methods :"POST,GET,PUT,DELETE,OPTIONS"
Allow :"POST"
Content-Length :"1721"
Content-Type :"text/html; charset=UTF-8"
Date :"Mon, 15 Jan 2018 08:28:17 GMT"
Server :"Microsoft-HTTPAPI/2.0"
我准备了一个简单的项目来测试我的服务:也许它会让人们更容易找出我的实现有什么问题。该项目的链接是here!
感谢任何额外帮助