解决WCF跨域问题,及DataTable参数问题
上一篇章配置了如何可以使用http方式调用wcf,在C#代码中可以使用HttpClient,HttpWebRequest等web类进行请求
但是如果直接使用js发送ajax请求的时候却会出现跨域问题
首先是web.config中的system.serviceModel节点配置
如下:
<system.serviceModel> <services> <service name="WcfService.ServiceAjax"> <endpoint address="" behaviorConfiguration="WcfService.ServiceAjaxAspNetAjaxBehavior" binding="webHttpBinding" contract="WCFlib.IClass" bindingConfiguration="webBinding"/> </service> </services> <bindings> <webHttpBinding> <binding name="webBinding" crossDomainScriptAccessEnabled="true" > </binding> </webHttpBinding> </bindings> <behaviors> <endpointBehaviors> <behavior name="WcfService.ServiceAjaxAspNetAjaxBehavior" > <webHttp automaticFormatSelectionEnabled="true" defaultBodyStyle="Wrapped" helpEnabled="true" defaultOutgoingResponseFormat="Json" faultExceptionEnabled="true"/> <!--<enableWebScript/> 这一个不能要,否则就不能使用ref或out参数了--> <dataContractSerializer ignoreExtensionDataObject="true"/> </behavior> </endpointBehaviors> <serviceBehaviors> <behavior name=""> <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="true" /> </behavior> </serviceBehaviors> </behaviors> <protocolMapping> <add binding="basicHttpsBinding" scheme="https" /> <add binding="basicHttpsBinding" scheme="http" /> <add binding="webHttpBinding" scheme="https"/> <add binding="webHttpBinding" scheme="http"/> </protocolMapping> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> </system.serviceModel>
主要的配置在service的endpoint里面的behaviorConfiguration,关于配置文件的详解,请查看上一篇
然后在wcf项目中添加一个全局配置文件
在里面的Application_BeginRequest方法中写入
protected void Application_BeginRequest(object sender, EventArgs e) { HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*"); if (HttpContext.Current.Request.HttpMethod != "OPTIONS") return; HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST"); HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept"); HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000"); HttpContext.Current.Response.End(); }
之后就可以使用了,当然,契约接口和契约实现类,也请参照上一篇章
让WCF支持Http调用
下面是调用的html文件
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8" /> <title></title> <script crossorigin="anonymous" integrity="sha512-WNLxfP/8cVYL9sj8Jnp6et0BkubLP31jhTG9vhL/F5uEZmg5wEzKoXp1kJslzPQWwPT1eyMiSxlKCgzHLOTOTQ==" src="https://lib.baomitu.com/jquery/3.5.1/jquery.js"></script> <script> $(function () { $('#btn').click(function () { $.ajax({ url: 'http://localhost:15500/ServiceAjax.svc/TestModel', type:'POST', data: '{\"name\":\"aaa\"}', async: false, dataType: "json", Accept:'*/*', contentType: 'application/json', success: function (data) { console.log(data) }, error: function (data) { console.log(data) } } ) }) }) </script> </head> <body> <button id="btn">Get</button> </body> </html>
下面是成功的截图
==========================
关于DataTable的参数问题
如果有是out类的则无须管
但如果是入参,例如以下方法
public string ParamterTable(DataTable table) { return "传递成功"; }
传递table的时候,应该如下传递 首先封装成一个json,然后DataTable的数据,需要是一个xml文档
该文档如下所示
<!--命名空间为固定的,必须如此,表示此处是一个DataTable类型--> <DataTable xmlns=\"http://schemas.datacontract.org/2004/07/System.Data\"> <!--schema定义DataTable的架构--> <xs:schema id=\"NewDataSet\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\"> <xs:element name=\"NewDataSet\" msdata:IsDataSet=\"true\" msdata:MainDataTable=\"table\" msdata:UseCurrentLocale=\"true\"> <xs:complexType> <xs:choice minOccurs=\"0\" maxOccurs=\"unbounded\"> <xs:element name=\"table\"> <xs:complexType> <xs:sequence> <xs:element name=\"ID\" type=\"xs:string\" minOccurs=\"0\"/> <xs:element name=\"Name\" type=\"xs:string\" minOccurs=\"0\"/> </xs:sequence> </xs:complexType> </xs:element> </xs:choice> </xs:complexType> </xs:element> </xs:schema> <!--定义DataTable的内容--> <diffgr:diffgram xmlns:diffgr=\"urn:schemas-microsoft-com:xml-diffgram-v1\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\"> <DocumentElement xmlns=\"\"> <!--table为此DataTable的名称,下面就是每一行的数据--> <!--注意diffgr:hasChanges特性,此处可取值 modified 表示该行已修改 inserted 表示该行为新添加--> <table diffgr:id=\"table1\" msdata:rowOrder=\"0\" diffgr:hasChanges=\"modified\"> <ID>0</ID> <Name>33</Name> </table> <table diffgr:id=\"table3\" msdata:rowOrder=\"2\"> <ID>2</ID> <Name>3</Name> </table> <table diffgr:id=\"table4\" msdata:rowOrder=\"3\"> <ID>3</ID> <Name>4</Name> </table> <table diffgr:id=\"table5\" msdata:rowOrder=\"4\"> <ID>4</ID> <Name>5</Name> </table> <table diffgr:id=\"table6\" msdata:rowOrder=\"5\" diffgr:hasChanges=\"inserted\"> <ID>1</ID> <Name>2</Name> </table> </DocumentElement> <!--此处为已经被删除的行标识 before表示该行之前的状态--> <diffgr:before> <!--表示将原有下标为1的行删除了,注意看上面没胡rowOrder=1的数据--> <table diffgr:id=\"table1\" msdata:rowOrder=\"0\" xmlns=\"\"> <ID>0</ID> <Name>1</Name> </table> <!--然后将之前第第二行下标为2的数据放到下标1上,而上面其实还将下标进行了升级--> <table diffgr:id=\"table2\" msdata:rowOrder=\"1\" xmlns=\"\"> <ID>1</ID> <Name>2</Name> </table> </diffgr:before> </diffgr:diffgram> </DataTable>
这是方法调用截图示例
总的来说,DataTable的参数传递和解析都是很麻烦的,如果是C#代码还好,解析和封装都不算困难,但如果是JS解析的话,那就很麻烦了