WebService是基於XML格式的,返回的默認結果是XML格式,因為它比較通用,幾乎任何編程語言、操作系統和應用程序都能方便的讀寫。
多番測試
方式一:最簡單的例子:
[WebMethod(MessageName = "默認返回對象")] public User GetXmlByObject() { User user = new User() {Id = 1, Name = "張三"}; return user; }
返回結果:
<?xml version="1.0" encoding="UTF-8"?> <User xmlns="http://tempuri.org/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Id>1</Id><Name>張三</Name></User>
方式二:WebService的輸入或輸出參數可以是對象,它會自動序列化XML格式,如果自己強加序列化一次,返回字符串,結果就是這樣:
[WebMethod(MessageName = "構造XML返回")] public string GetXmlByXml() { User user = new User() { Id = 2, Name = "張三豐" }; return SerializeToXml(user); }
返回結果:
<?xml version="1.0" encoding="UTF-8"?> <string xmlns="http://tempuri.org/"><?xml version="1.0" encoding="utf-8"?><User xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Id>2</Id><Name>張三豐</Name></User></string>
方式三:隨着JSON的流行,更多的網頁、移動端都需要JSON格式。於是,就把它序列化JSON串返回(我一直都是這樣操作的)
[WebMethod(MessageName = "構造JSON返回")] public string GetXmlByJson() { User user = new User() { Id = 3, Name = "李四" }; //添加Newtonsoft.Json進行序列化 return JsonConvert.SerializeObject(user); }
返回結果:
<?xml version="1.0" encoding="UTF-8"?> <string xmlns="http://tempuri.org/">{"Id":3,"Name":"李四"}</string>
方式四:如果將對象反序列化成JSON字符串,返回包含json字符串的XML格式,前端總要有一個解析過程,不是很方便!有沒有返回直接是JSON格式的?有。
[WebMethod(MessageName = "Response.Write")] public void GetXmlByResponse() { User user = new User() { Id = 4, Name = "李世民" }; Context.Response.Write(JsonConvert.SerializeObject(user)); Context.Response.End(); }
返回結果:
{"Id":4,"Name":"李世民"}
解決方案
上面最后一 種測試雖然能達到效果,但每個接口中都要這樣操作,顯得有點"笨",當然想要高級的自行車。
第一步,在工程中新建AsmxRequestModule.cs和CatchTextStream.cs文件,並實現它。
AsmxRequestModule代碼如下:
public class AsmxRequestModule: IHttpModule { public void Init(HttpApplication context) { context.BeginRequest += new EventHandler(Application_BeginRequest); } public void Dispose() { } public void Application_BeginRequest(object sender, EventArgs e) { HttpApplication application = sender as HttpApplication; string extension = Path.GetExtension(application.Request.Path); if (application.Request.Path.IndexOf(".asmx/") > -1) { application.Response.Filter = new CatchTextStream(application.Response.Filter); } } }
CatchTextStream代碼如下:
public class CatchTextStream: Stream { #region 數據流 /// <summary> /// 數據流 /// </summary> private readonly Stream output; #endregion #region 構造函數 public CatchTextStream(Stream s) { output = s; } #endregion #region 重載屬性及方法 public override bool CanRead => output.CanRead; public override bool CanSeek => output.CanSeek; public override bool CanWrite => output.CanWrite; public override void Flush() { output.Flush(); } public override long Length => output.Length; public override long Position { get => output.Position; set => output.Position = value; } public override int Read(byte[] buffer, int offset, int count) { return output.Read(buffer, offset, count); } public override long Seek(long offset, SeekOrigin origin) { return output.Seek(offset, origin); } public override void SetLength(long value) { output.SetLength(value); } public override void Write(byte[] buffer, int offset, int count) { if (HttpContext.Current != null) { HttpContext context = HttpContext.Current; Encoding encoding = context.Response.ContentEncoding; string responseInfo = encoding.GetString(buffer, offset, count); responseInfo = responseInfo.Replace("<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<string xmlns=\"http://tempuri.org/\">", ""); responseInfo = responseInfo.Substring(0, responseInfo.Length - 9); buffer = encoding.GetBytes(responseInfo); output.Write(buffer, 0, buffer.Length); } } #endregion }
第二步,修改web.config ,在配置中增加modules配置。
<configuration> …… <system.webServer> …… <modules> <add name="AsmxRequestModule" type="命名空間.AsmxRequestModule"/> </modules> …… </system.webServer> …… </configuration>
第三步,按“構造JSON對象”(第三種)的方式書寫接口即可。