什么是服务参考的正确url?
我有两个项目,一个是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。
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 } } }); }
因为我收到404错误,所以我觉得url错了。 请参阅文件的结构,我猜这个Web引用叫做’ServiceReference1’。
如屏幕截图所示,该服务未托管在您的Web应用程序中。 您无法直接从客户端访问此类服务(在Web应用程序之外托管),因为您违反了相同的原始策略限制。 它是信任的基本概念之一,Web安全基于此(例如,保护aganist XSS ) – 您无法发送跨域AJAX请求。 这基本上表明,如果来自一个站点(例如https://bank.ny.com
)的内容被授予访问系统上的资源的权限,那么来自该站点的任何内容将共享这些权限,而来自另一个站点的内容( https://nsa.ny.com
)必须单独授予权限(通常,术语origin是使用域名,应用程序层协议和端口号定义的)。
不过,您至少有4种解决方案可以解决您的问题:
首先 – 通过中间控制器层与您的服务对话。 这样做意味着生成代理类(通过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服务:
对于RESTful端点,您应该使用的绑定是WebHttpBinding
以及适当的行为。 另外,对于许多RESTful服务WebServiceHostFactory
都有免配置的体验。 您的.svc文件应如下所示( MSDN ):
<%@ ServiceHost Language="C#" Debug="true" Service="Namespace.Service1" CodeBehind="Service1.svc.cs" Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>
WebServiceHostFactory
创建WebServiceHostFactory
的实例,并且由于WebServiceHost
将使用WebHttpBinding
和相关行为自动配置端点,因此根本不需要在web.config中对此端点进行任何配置(当然,如果需要)要自定义绑定,您必须使用配置)( MSDN )。
然后访问该服务使用适当的完整URL: http://localhost:[port]/Service1.svc/RunTts
或相对的一个: /Service1.svc/RunTts
。
由于您正在使用ASP.NET MVC,基于您的路由定义,请求将被分派到某个控制器,此类操作不存在。 您必须告诉MVC忽略您的服务路由:
routes.IgnoreRoute("{resource}.svc/{*pathInfo}");
(顺便说一句:如果您将.svc文件放在应用程序的不同目录下,请分别修改URL和路由以忽略。)
您的代码需要一些额外的修复:
-
如果要以JSON格式发送消息,请正确指定
dataType
和contentType
参数:$.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); ...
-
从项目中删除服务引用。 你不需要它,因为这里没有使用中间控制器。
第三 – JSONP ( 在这里和这里看)可用于克服原始政策限制。 但是你不能使用JSONP进行POST,因为它不会那样工作 – 它会创建一个元素来获取数据,这必须通过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配置:
第四 - CORS 。 在现代浏览器中实现替代 JSON with Padding。
- 从嵌套集合中添加/删除MVC4(使用jQuery?)
- 如何实现在MVC和jquery中为FileUploading附加更多文件
- asp.net mvc,带有jqueryvalidation和Html.EditorFor以及不同的decimalseparators
- 字段日期必须是镶嵌在mvc中的日期
- 0x800a1391 – JavaScript运行时错误:’jQuery’未定义 – MVC 4
- 如何在我的JQUERY提交中添加其他数据?
- Url.Action:如何将参数从View传递给Controller?
- window.location或window.location.href没有更改所有浏览器MVC应用程序中的值
- 使用jQuery Validate不会命中远程操作方法