gpt4 book ai didi

wcf - 服务引用的正确 url 是什么?

转载 作者:行者123 更新时间:2023-12-01 06:49:19 24 4
gpt4 key购买 nike

我有两个项目,一个是 WCF 服务,它是在文本框中说出文本/句子。

public class Service1 : IService1
{
public string RunTts(string text)
{
using (SpeechSynthesizer synth = new SpeechSynthesizer())
{
// Configure the audio output.
synth.SetOutputToDefaultAudioDevice();
synth.Speak(text);
return "";
}
}
}

然后我在第二个项目的_Layout.cshtml页面中用ajax调用,也就是asp.net mvc。
<script type="text/javascript">
function ttsFunction() {
serviceUrl = "Service1.svc/RunTts";

$.ajax({
type: "POST",
url: serviceUrl,
data: '{"text": "' + $('#speak').val() + '"}',
contentType: "text/xml; charset=utf-8",
dataType: "text/xml",
error: function (xhr,status,error) {
console.log("Status: " + status); // got "error"
console.log("Error: " + error); // got "Not Found"
console.log("xhr: " + xhr.readyState); // got "4"
},
statusCode: {
404: function() {
console.log("page not found"); // got
}
}
});
}
</script>

因为我得到了 404 错误,所以我认为 url 是错误的。请查看文件的结构,我猜网络引用称为“ServiceReference1”。
picture

最佳答案

如您的屏幕截图所示,该服务未托管在您的 Web 应用程序中。您不能直接从客户端访问这样的服务(托管在您的 Web 应用程序之外),因为您违反了 same origin policy限制。它是信任的基本概念之一,Web 安全基于它(例如保护反叛者 XSS ) - 您不能发送跨域 AJAX 请求。这实质上表明,如果来自一个站点的内容(例如 https://bank.ny.com )被授予访问系统资源的权限,那么来自该站点的任何内容都将共享这些权限,而来自另一个站点的内容( https://nsa.ny.com )必须是分别授予权限(通常,术语起源是使用域名、应用层协议(protocol)和端口号定义的)。

尽管如此,您至少有 4 个解决方案来解决您的问题:

第一 - 通过中间 Controller 层与您的服务对话。采用这种方式意味着生成代理类(通过 svcutil.exe,您通过使用 Visual Studio 添加服务引用来完成)。与该客户端的通信如下所示:

public class TtsController
{
public JsonResult RunTts(string text)
{
using(var client = new ServiceReference1.Service1Client())
{
var response = client.RunTts(text);
return Json(response);
...

JavaScript 端应该使用这样的 URL: var serviceUrl = "/Tts/RunTts" (以及传递给 AJAX 请求的正确 JSON 数据,我将进一步介绍)。

第二 - 直接与服务交谈。如果您想直接与该服务通信,则必须在您的 Web 应用程序中托管该服务。应遵循正确的 WCF 配置以支持 RESTful 服务:

<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="webby">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="Namespace.Service1">
<endpoint address=""
behaviorConfiguration="webby"
binding="webHttpBinding"
contract="Namespace.IService1" />
</service>
</services>
</system.serviceModel>

对于 RESTful 端点,您应该使用的绑定(bind)是 WebHttpBinding以及适当的行为。或者,有许多 RESTful 服务的免配置体验 - WebServiceHostFactory .您的 .svc 文件应如下所示( MSDN):
<%@ ServiceHost Language="C#" Debug="true" Service="Namespace.Service1"
CodeBehind="Service1.svc.cs"
Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>
WebServiceHostFactory创建 WebServiceHost 的实例,并且由于 WebServiceHost将使用 WebHttpBinding 自动配置端点和相关的行为,web.config 中根本不需要对此端点进行任何配置(当然,如果需要自定义绑定(bind),则必须使用配置)( MSDN )。

然后使用适当的完整 URL 访问服务: http://localhost:[port]/Service1.svc/RunTts或相对: /Service1.svc/RunTts .

由于您使用的是 ASP.NET MVC,因此根据您的路由定义,请求将分派(dispatch)到不存在此类操作的某个 Controller 。您必须告诉 MVC 忽略到您的服务的路由:
routes.IgnoreRoute("{resource}.svc/{*pathInfo}");

(顺便说一句:如果您将 .svc 文件放在应用程序中的不同目录下,请分别修改 URL 和路由以忽略。)

您的代码需要一些额外的修复:
  • 如果要发送 JSON 格式的消息,请指定 dataTypecontentType参数正确:
    $.ajax({
    url: serviceUrl,
    type: "POST",
    dataType: "json",
    contentType: "application/json; charset=utf-8",
    ...
  • 不要手动构建 JSON 字符串,因为它可能导致进一步的解析错误 - 使用转换器,例如:
    var data = new Object();
    data.text = $('#speak').val();
    var jsonString = JSON.stringify(data);

    $.ajax({
    ...
    data: jsonString,
    ...
  • 为您的服务提供额外的声明性信息:
    [ServiceContract]
    public interface IService1
    {
    [OperationContract]
    [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)]
    string RunTts(string text);
    ...
  • 从项目中删除服务引用。您不需要它,因为这里没有使用中间 Controller 。

  • 第三 - JSONP (看 herehere )可用于克服原产地政策限制。但是您不能使用 JSONP 发布,因为它只是 doesn't work that way - 它创建一个 <script>元素来获取数据,这必须通过 GET 请求来完成。 JSONP 解决方案不使用 XmlHttpRequest对象,所以它不是标准理解方式的 AJAX 请求,但内容仍然是动态访问的——对于最终用户来说没有区别。
    $.ajax({
    url: serviceUrl,
    dataType: "jsonp",
    contentType: "application/json; charset=utf-8",
    data: data,
    ...

    [OperationContract]
    [WebGet(RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate="RunTts?text={text}")]
    public string RunTts(string text);

    允许跨域请求的 RESTful WCF 配置:

    <system.serviceModel>
    <bindings>
    <webHttpBinding>
    <binding name="jsonp" crossDomainScriptAccessEnabled="true" />
    </webHttpBinding>
    </bindings>
    <behaviors>
    <endpointBehaviors>
    <behavior name="webby">
    <webHttp />
    </behavior>
    </endpointBehaviors>
    <serviceBehaviors>
    <behavior>
    <serviceMetadata httpGetEnabled="true" />
    </behavior>
    </serviceBehaviors>
    </behaviors>
    <services>
    <service name="Namespace.Service1">
    <endpoint address=""
    behaviorConfiguration="webby"
    binding="webHttpBinding"
    bindingConfiguration="jsonp"
    contract="Namespace.IService1" />
    </service>
    </services>
    </system.serviceModel>

    第四 - CORS .在现代浏览器中实现 alternative到带有填充的 JSON。

    关于wcf - 服务引用的正确 url 是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17489707/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com