通过 HTTPS 向 WCF 自托管 REST 服务发出 POST 请求的示例
Example of a POST request to WCF selfhosted REST service over HTTPS
SO 上有许多关于同一主题的问题,但其中 none 似乎给出了完整的答案。 questions/answers大部分我都查过了,测试了,测试了再测试。所以希望这个问题能帮助我和其他苦苦挣扎的人。
问题.
如何设置通过 https 运行的 WCF 自托管 REST 服务?
这就是我尝试设置服务和客户端的方式。它不起作用!但是我觉得我每一次改变都很接近,但我没有达到目标。
那么,有人可以帮助我提供一个完整示例,该示例使用 REST 端点、基于 HTTPS 的自托管 WCF 和 POST 请求吗?我试过拼凑来自各地的点点滴滴,但我无法让它发挥作用!
我该放弃吗?选择其他技术?
所以,一些代码:
[服务主机]
Uri uri = new Uri("https://localhost:443");
WebHttpBinding binding = new WebHttpBinding(WebHttpSecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
using (ServiceHost sh = new ServiceHost(typeof(Service1), uri))
{
ServiceEndpoint se = sh.AddServiceEndpoint(typeof(IService1), binding, "");
//se.EndpointBehaviors.Add(new WebHttpBehavior());
// Check to see if the service host already has a ServiceMetadataBehavior
ServiceMetadataBehavior smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
// If not, add one
if (smb == null)
smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = false; //**http**
smb.HttpsGetEnabled = true; //**https**
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
sh.Description.Behaviors.Add(smb);
// Add MEX endpoint
sh.AddServiceEndpoint(
ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexHttpsBinding(), //**https**
"mex"
);
var behaviour = sh.Description.Behaviors.Find<ServiceBehaviorAttribute>();
behaviour.InstanceContextMode = InstanceContextMode.Single;
Console.WriteLine("service is ready....");
sh.Open();
Console.ReadLine();
sh.Close();
}
[I服务]
[ServiceContract]
public interface IService1
{
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Xml, RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest, UriTemplate = "Datarows_IN/")]
[OperationContract]
bool Save(BatchOfRows batchOfRows);
}
[服务]
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
public class Service1 : IService1
{
public bool Save(BatchOfRows batchOfRows)
{
Console.WriteLine("Entered Save");
return true;
}
}
[BatchOfRows] - 简化
[DataContract]
public class BatchOfRows
{
[DataMember]
public int ID { get; set; } = -1;
[DataMember]
public string Data { get; set; } = "Hej";
}
这是在 SO 答案和 Microsoft 教程之后建立的。
我什至不知道什么例子从哪里开始,其他例子从哪里结束。
我从这里开始:
在我尝试启用 https 之前,它工作得很好,然后一切都停止了。
这是我试过的一些客户端代码。
[网络客户端]
string uri = "https://localhost:443/Datarows_IN";
WebClient client = new WebClient();
client.Headers["Content-type"] = "application/json";
client.Encoding = Encoding.UTF8;
var b = new BatchOfRows();
var settings = new JsonSerializerSettings() { DateFormatHandling = DateFormatHandling.MicrosoftDateFormat };
string str2 = "{\"batchOfRows\":" + JsonConvert.SerializeObject(b, settings) + "}";
string result = client.UploadString(uri, "POST", str2);
[HttpClient]
string str2 = "{\"batchOfRows\":" + JsonConvert.SerializeObject(b, settings) + "}";
var contentData = new StringContent(str2, System.Text.Encoding.UTF8, "application/json");
//string result = client.UploadString(uri, "POST", str2);
//HttpResponseMessage response = client.PostAsJsonAsync("https://localhost:443/Datarows_IN", b).GetAwaiter().GetResult();
HttpResponseMessage response = client.PostAsync("https://localhost:443/Datarows_IN", contentData).GetAwaiter().GetResult();
response.EnsureSuccessStatusCode();
[频道工厂]
//var c = new ChannelFactory<IService1>(binding, new EndpointAddress("https://localhost:443/Datarows_IN"));
var c = new ChannelFactory<IService1>(binding, new EndpointAddress("https://localhost:443/"));
((WebHttpBinding)c.Endpoint.Binding).Security.Mode = WebHttpSecurityMode.Transport;
((WebHttpBinding)c.Endpoint.Binding).Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
c.Endpoint.Behaviors.Add(new WebHttpBehavior());
var aw = c.CreateChannel();
var b = new ModuleIntegration.Client.Objects.BatchOfRows();
aw.Save(b);
None 的客户工作。如果我调试我的服务端点永远不会被触发。
这是我得到的当前错误:
<Fault xmlns="http://schemas.microsoft.com/ws/2005/05/envelope/none">
<Code>
<Value>Sender</Value>
<Subcode>
<Value xmlns:a="http://schemas.microsoft.com/ws/2005/05/addressing/none">a:ActionNotSupported</Value>
</Subcode>
</Code>
<Reason>
<Text xml:lang="sv-SE">The message with Action '' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).</Text>
</Reason>
</Fault>
请帮忙!为什么这么难?!?
您的服务缺少 WebHttpBehavior
。
没有它,WebInvoke
属性什么都不做,路径 "Datarows_IN"
不会被识别为一个动作。
这是完整的(适合我的)服务主机代码:
var binding = new WebHttpBinding()
{
Security = {
Mode = WebHttpSecurityMode.Transport
}
};
var baseUri = new Uri("https://localhost:443");
using (ServiceHost sh = new ServiceHost(typeof(Service1), baseUri))
{
var metadata = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (metadata == null) {
metadata = new ServiceMetadataBehavior();
sh.Description.Behaviors.Add(metadata);
}
metadata.HttpsGetEnabled = true;
var endpoint = sh.AddServiceEndpoint(typeof(IService1), binding, "/");
endpoint.EndpointBehaviors.Add(new WebHttpBehavior());
Console.WriteLine("Service is ready....");
sh.Open();
Console.WriteLine("Service started. Press <ENTER> to close.");
Console.ReadLine();
sh.Close();
}
你的代码片段看起来很谨慎,导致了上面的错误,即我们应该添加WebHttpBehavior。
但是,还有一点需要注意。
通常,当我们在 IIS 中通过 HTTPS 托管服务时,服务需要提供证书来加密和签署服务器端和客户端之间的通信。
因此,理论上我们在使用自托管时应该绑定证书,否则服务将无法正常使用。
为什么这个服务端点地址运行良好?唯一的解释就是我们在某处绑定了证书到端口,比如IIS,有网站绑定了https,使用默认端口。
如果自定义端口未与证书关联,我们应该使用以下命令绑定证书。
Netsh http add sslcert ipport=0.0.0.0:portnumber
certhash=0000000000003ed9cd0c315bbb6dc1c08da5e6
appid={00112233-4455-6677-8899-AABBCCDDEEFF}
https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-configure-a-port-with-an-ssl-certificate
https://docs.microsoft.com/en-us/windows/win32/http/add-sslcert
默认情况下,证书只能在存储在本地计算机而不是当前用户中时设置。我们可以使用以下命令管理证书。
Certlm.msc
祝你好运。
最后,WCF 并不是针对设计 Restful 风格的服务。我们应该考虑 Asp.net WebAPI。
https://docs.microsoft.com/en-us/aspnet/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api
如果有什么我可以帮忙的,请随时告诉我。
SO 上有许多关于同一主题的问题,但其中 none 似乎给出了完整的答案。 questions/answers大部分我都查过了,测试了,测试了再测试。所以希望这个问题能帮助我和其他苦苦挣扎的人。
问题.
如何设置通过 https 运行的 WCF 自托管 REST 服务? 这就是我尝试设置服务和客户端的方式。它不起作用!但是我觉得我每一次改变都很接近,但我没有达到目标。
那么,有人可以帮助我提供一个完整示例,该示例使用 REST 端点、基于 HTTPS 的自托管 WCF 和 POST 请求吗?我试过拼凑来自各地的点点滴滴,但我无法让它发挥作用! 我该放弃吗?选择其他技术?
所以,一些代码:
[服务主机]
Uri uri = new Uri("https://localhost:443");
WebHttpBinding binding = new WebHttpBinding(WebHttpSecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
using (ServiceHost sh = new ServiceHost(typeof(Service1), uri))
{
ServiceEndpoint se = sh.AddServiceEndpoint(typeof(IService1), binding, "");
//se.EndpointBehaviors.Add(new WebHttpBehavior());
// Check to see if the service host already has a ServiceMetadataBehavior
ServiceMetadataBehavior smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
// If not, add one
if (smb == null)
smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = false; //**http**
smb.HttpsGetEnabled = true; //**https**
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
sh.Description.Behaviors.Add(smb);
// Add MEX endpoint
sh.AddServiceEndpoint(
ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexHttpsBinding(), //**https**
"mex"
);
var behaviour = sh.Description.Behaviors.Find<ServiceBehaviorAttribute>();
behaviour.InstanceContextMode = InstanceContextMode.Single;
Console.WriteLine("service is ready....");
sh.Open();
Console.ReadLine();
sh.Close();
}
[I服务]
[ServiceContract]
public interface IService1
{
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Xml, RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest, UriTemplate = "Datarows_IN/")]
[OperationContract]
bool Save(BatchOfRows batchOfRows);
}
[服务]
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
public class Service1 : IService1
{
public bool Save(BatchOfRows batchOfRows)
{
Console.WriteLine("Entered Save");
return true;
}
}
[BatchOfRows] - 简化
[DataContract]
public class BatchOfRows
{
[DataMember]
public int ID { get; set; } = -1;
[DataMember]
public string Data { get; set; } = "Hej";
}
这是在 SO 答案和 Microsoft 教程之后建立的。
我什至不知道什么例子从哪里开始,其他例子从哪里结束。
我从这里开始:
这是我试过的一些客户端代码。
[网络客户端]
string uri = "https://localhost:443/Datarows_IN";
WebClient client = new WebClient();
client.Headers["Content-type"] = "application/json";
client.Encoding = Encoding.UTF8;
var b = new BatchOfRows();
var settings = new JsonSerializerSettings() { DateFormatHandling = DateFormatHandling.MicrosoftDateFormat };
string str2 = "{\"batchOfRows\":" + JsonConvert.SerializeObject(b, settings) + "}";
string result = client.UploadString(uri, "POST", str2);
[HttpClient]
string str2 = "{\"batchOfRows\":" + JsonConvert.SerializeObject(b, settings) + "}";
var contentData = new StringContent(str2, System.Text.Encoding.UTF8, "application/json");
//string result = client.UploadString(uri, "POST", str2);
//HttpResponseMessage response = client.PostAsJsonAsync("https://localhost:443/Datarows_IN", b).GetAwaiter().GetResult();
HttpResponseMessage response = client.PostAsync("https://localhost:443/Datarows_IN", contentData).GetAwaiter().GetResult();
response.EnsureSuccessStatusCode();
[频道工厂]
//var c = new ChannelFactory<IService1>(binding, new EndpointAddress("https://localhost:443/Datarows_IN"));
var c = new ChannelFactory<IService1>(binding, new EndpointAddress("https://localhost:443/"));
((WebHttpBinding)c.Endpoint.Binding).Security.Mode = WebHttpSecurityMode.Transport;
((WebHttpBinding)c.Endpoint.Binding).Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
c.Endpoint.Behaviors.Add(new WebHttpBehavior());
var aw = c.CreateChannel();
var b = new ModuleIntegration.Client.Objects.BatchOfRows();
aw.Save(b);
None 的客户工作。如果我调试我的服务端点永远不会被触发。 这是我得到的当前错误:
<Fault xmlns="http://schemas.microsoft.com/ws/2005/05/envelope/none">
<Code>
<Value>Sender</Value>
<Subcode>
<Value xmlns:a="http://schemas.microsoft.com/ws/2005/05/addressing/none">a:ActionNotSupported</Value>
</Subcode>
</Code>
<Reason>
<Text xml:lang="sv-SE">The message with Action '' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).</Text>
</Reason>
</Fault>
请帮忙!为什么这么难?!?
您的服务缺少 WebHttpBehavior
。
没有它,WebInvoke
属性什么都不做,路径 "Datarows_IN"
不会被识别为一个动作。
这是完整的(适合我的)服务主机代码:
var binding = new WebHttpBinding()
{
Security = {
Mode = WebHttpSecurityMode.Transport
}
};
var baseUri = new Uri("https://localhost:443");
using (ServiceHost sh = new ServiceHost(typeof(Service1), baseUri))
{
var metadata = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (metadata == null) {
metadata = new ServiceMetadataBehavior();
sh.Description.Behaviors.Add(metadata);
}
metadata.HttpsGetEnabled = true;
var endpoint = sh.AddServiceEndpoint(typeof(IService1), binding, "/");
endpoint.EndpointBehaviors.Add(new WebHttpBehavior());
Console.WriteLine("Service is ready....");
sh.Open();
Console.WriteLine("Service started. Press <ENTER> to close.");
Console.ReadLine();
sh.Close();
}
你的代码片段看起来很谨慎,导致了上面的错误,即我们应该添加WebHttpBehavior。
但是,还有一点需要注意。
通常,当我们在 IIS 中通过 HTTPS 托管服务时,服务需要提供证书来加密和签署服务器端和客户端之间的通信。
因此,理论上我们在使用自托管时应该绑定证书,否则服务将无法正常使用。
为什么这个服务端点地址运行良好?唯一的解释就是我们在某处绑定了证书到端口,比如IIS,有网站绑定了https,使用默认端口。
如果自定义端口未与证书关联,我们应该使用以下命令绑定证书。
Netsh http add sslcert ipport=0.0.0.0:portnumber certhash=0000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00112233-4455-6677-8899-AABBCCDDEEFF}
https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-configure-a-port-with-an-ssl-certificate
https://docs.microsoft.com/en-us/windows/win32/http/add-sslcert
默认情况下,证书只能在存储在本地计算机而不是当前用户中时设置。我们可以使用以下命令管理证书。
Certlm.msc
祝你好运。
最后,WCF 并不是针对设计 Restful 风格的服务。我们应该考虑 Asp.net WebAPI。
https://docs.microsoft.com/en-us/aspnet/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api
如果有什么我可以帮忙的,请随时告诉我。