代码改变世界

ASP.NET 中 Web Service 的使用简单案例

2012-05-28 18:20  音乐让我说  阅读(1329)  评论(0编辑  收藏  举报

对于 Web Service,我想大家都已经很熟悉了,笔者也是,几年前就搞过,在现在 WCF 的侵蚀下,Web Service 似乎已经被人们所忘记,这次因为项目所需要,重新拾起来,发现都快忘记了,比如在允许 Javascript 调用 Web Service,忘记取消注释 [System.Web.Script.Services.ScriptService] 了,导致调试了许久。好了,废话不多说了,开始示例了。

1. 首先建一个 Web Service 项。由于说明都已经写在项目中了,故直接贴代码了。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using DearBruce.NewsAPI.MvcUI.Models;
using System.Xml.Serialization;

namespace DearBruce.NewsAPI.MvcUI.Api
{
    /// <summary>
    /// NewsService 的摘要说明
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // 若要允许使用 AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。
    [System.Web.Script.Services.ScriptService] 
    public class NewsService : System.Web.Services.WebService
    {
        private static List<Contact> contacts = new List<Contact>
        {
            new Contact{ Id = "001", FirstName = "San", LastName="Zhang", PhoneNo="123", EmailAddress="zhangsan@gmail.com"},
            new Contact{ Id = "002", FirstName = "", LastName="", PhoneNo="456", EmailAddress="lisi@gmail.com"},
            new Contact{ Id = "003", FirstName = "斯蒂芬Say<span> \"Hello World;\";</span>", LastName="李<div;''\\|#%&;", PhoneNo="456", EmailAddress="shidifen@gmail.com"}
        };

        [WebMethod(Description = "HelloWorld 示例")]
        public string HelloWorld()
        {
            return "Hello World";
        }

        [WebMethod(Description = "Get 所有记录")]
        public Contact[] Get()
        {
            return contacts.ToArray();
        }

        [WebMethod(Description = "根据 ID 得到记录")]
        public Contact GetById(string id)
        {
            return contacts.FirstOrDefault(c => c.Id == id);
        }

        [WebMethod(Description = "附加一条记录")]
        [XmlInclude(typeof(Contact))]
        public string AddContact(Contact contact)
        {
            return Add(contact.FirstName, contact.LastName, contact.PhoneNo, contact.EmailAddress, contact.Id);
        }

        [WebMethod(Description = "附加一条记录")]
        public string Add(string firstName, string lastName, string phoneNo, string emailAddress, string id = "")
        {
            Contact contact = new Contact();
            if (string.IsNullOrEmpty(id))
            {
                contact.Id = Guid.NewGuid().ToString();
            }
            else
            {
                contact.Id = id;
            }
            if (GetById(contact.Id) != null)
            {
                return "0";
            }
            if (string.IsNullOrEmpty(firstName) || string.IsNullOrEmpty(lastName))
            {
                return "0";
            }
            contact.FirstName = firstName;
            contact.LastName = lastName;
            contact.PhoneNo = phoneNo;
            contact.EmailAddress = emailAddress;
            contacts.Add(contact);
            return "1";
        }

        [WebMethod(Description = "修改")]
        [XmlInclude(typeof(Contact))]
        public string UpdateContact(Contact contact)
        {
            return Update(contact.Id, contact.FirstName, contact.LastName, contact.PhoneNo, contact.EmailAddress);
        }

        [WebMethod(Description = "修改")]
        public string Update(string id, string firstName, string lastName, string phoneNo, string emailAddress)
        {
            if (string.IsNullOrEmpty(id))
            {
                return "0";
            }
            Contact contact = GetById(id);
            if (contact == null)
            {
                return "0";
            }
            contact.FirstName = firstName;
            contact.LastName = lastName;
            contact.PhoneNo = phoneNo;
            contact.EmailAddress = emailAddress;
            return "1";
        }

        [WebMethod(Description = "根据 ID 删除一条记录")]
        public string Delete(string id)
        {
            Contact contact = GetById(id);
            if (contact == null)
            {
                return "0";
            }
            contacts.Remove(contact);
            return "1";
        }
    }
}

2. 本项目调用。

@{
    ViewBag.Title = "主页";
}

<h2>@ViewBag.Message</h2>
<p>
    新闻API:<a href="/api/NewsService.asmx" target="_blank">点击这里</a>
</p>
<style type="text/css">
    div.hideDiv { display:none; margin:20px 0px; border: 1px solid red; line-height:30px; padding:10px; }
</style>
<div>
    <input type="button" value="调用 Hello World" onclick="invoke1();" /><br /><br />
    <input type="button" value="调用 Get,得到所有记录" onclick="invoke2();" /><br /><br />
    <input type="button" value="调用 GetById" onclick="invoke3();" /><br />
    <div id="divInvoke3" class="hideDiv">
        请输入 ID:<input type="text" id="txtInvoke3_Id" /><br />
        <input type="button" value="确定调用" onclick="invoke3Core();" /><br />
    </div>
    <br /><br />
    <input type="button" value="调用 Add" onclick="invoke4();" /><br />
    <div id="divInvoke4" class="hideDiv">
        请输入 ID:<input type="text" id="txtInvoke4_Id" /><br />
        请输入 FirstName:<input type="text" id="txtInvoke4_FirstName" /><br />
        请输入 LastName:<input type="text" id="txtInvoke4_LastName" /><br />
        请输入 PhoneNo:<input type="text" id="txtInvoke4_PhoneNo" /><br />
        请输入 EmailAddress:<input type="text" id="txtInvoke4_EmailAddress" /><br />
        <input type="button" value="确定调用" onclick="invoke4Core();" /><br />
    </div>
    <br /><br />
    <input type="button" value="调用 Delete" onclick="invoke5();" /><br />
    <div id="divInvoke5" class="hideDiv">
        请输入 ID:<input type="text" id="txtInvoke5_Id" /><br />
        <input type="button" value="确定调用" onclick="invoke5Core();" /><br />
    </div>
    <br /><br />
    <input type="button" value="JSONP 跨域调用 HelloWorld" onclick="invoke6();" /><br />
    <br /><br />
</div>
<script type="text/javascript">
    var baseUrl = "/api/NewsService.asmx/";   // http://newsapi.DearBruce.com:8020
    function invoke1()
    {
        $.ajax({
            type: "POST",   //访问WebService必须使用Post方式请求
            url: baseUrl + "HelloWorld", //调用WebService的地址和方法名称组合 ---- WsURL/方法名  
            dataType: 'xml',    
            success: function (result)
            {     //响应的类型为 xml,结构为:
                /*
                <?xml version="1.0" encoding="utf-8"?>
                <string xmlns="http://tempuri.org/">Hello World</string>
                */
                alert($(result).text()); // 弹出 Hello World
            },
            error: function (XMLHttpRequest, textStatus, errorThrown)
            {
                alert("调用失败!可能是服务提供商不允许 Ajax 来调用!");
            }
        });
    }
    function invoke2()
    {
        $.ajax({
            type: "POST",   //访问WebService必须使用Post方式请求
            url: baseUrl + "Get", //调用WebService的地址和方法名称组合 ---- WsURL/方法名  
            dataType: 'xml',
            success: function (result)
            {     //响应的类型为 xml,结构为:
                /*
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfContact xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">
  <Contact>
    <Id>001</Id>
    <FirstName>San</FirstName>
    <LastName>Zhang</LastName>
    <PhoneNo>123</PhoneNo>
    <EmailAddress>zhangsan@gmail.com</EmailAddress>
  </Contact>
  <Contact>
    <Id>002</Id>
    <FirstName>四</FirstName>
    <LastName>李</LastName>
    <PhoneNo>456</PhoneNo>
    <EmailAddress>lisi@gmail.com</EmailAddress>
  </Contact>
  <Contact>
    <Id>003</Id>
    <FirstName>斯蒂芬Say&lt;span&gt; "Hello World;";&lt;/span&gt;</FirstName>
    <LastName>李&lt;div;''\|#%&amp;;</LastName>
    <PhoneNo>456</PhoneNo>
    <EmailAddress>lisi@gmail.com</EmailAddress>
  </Contact>
</ArrayOfContact>
                */
                ShowMoreContact(result);
            },
            error: function (XMLHttpRequest, textStatus, errorThrown)
            {
                alert("调用失败!可能是服务提供商不允许 Ajax 来调用!");
            }
        });
    }

    function ShowMoreContact(result)
    {
        var jContactItems = $(result).find("Contact");
        if (jContactItems.eq(0).find("Id").text() == "")
        {
            alert("没有数据");
            return;
        }
        jContactItems.each(function (i, item)
        {
            var jItem = $(item);
            var id = jItem.find("Id").text(); // 如果是以属性的方式提供的值,那么就需要用 jItem.attr("Id")
            var firstName = jItem.find("FirstName").text();
            var lastName = jItem.find("LastName").text();
            var phoneNo = jItem.find("PhoneNo").text();
            var emailAddress = jItem.find("EmailAddress").text();
            alert("" + (i + 1) + "条数据。\n Id:" + id + "\n firstName:" + firstName
                         + "\n lastName:" + lastName + "\n phoneNo:" + phoneNo + "\n emailAddress:" + emailAddress);
        });
    }
    
    function showOrHideDiv(divId)
    {
        var currentDiv = $("#" + divId);
        var displayValue = currentDiv.css("display");
        if (displayValue == "none")
        {
            //currentDiv.css("display", "block");
            currentDiv.show();
        }
        else
        {
            //currentDiv.css("display", "none");
            currentDiv.hide();
        }
    }
    function invoke3()
    {
        showOrHideDiv("divInvoke3");
    }
    function invoke3Core()
    {
        var id = $.trim($("#txtInvoke3_Id").val());
        $.ajax({
            type: "POST",   //访问WebService必须使用Post方式请求
            url: baseUrl + "GetById", //调用WebService的地址和方法名称组合 ---- WsURL/方法名  
            dataType: 'xml',
            data: { id : id },
            success: function (result)
            {
//如果有数据,响应的类型为 xml,结构为:
/*
<?xml version="1.0" encoding="utf-8"?>
<Contact xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">
  <Id>001</Id>
  <FirstName>San</FirstName>
  <LastName>Zhang</LastName>
  <PhoneNo>123</PhoneNo>
  <EmailAddress>zhangsan@gmail.com</EmailAddress>
</Contact>
*/

//如果没有数据,响应的类型为 xml,结构为:
/*
 <?xml version="1.0" encoding="utf-8"?>
 <Contact xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:nil="true" xmlns="http://tempuri.org/" />
*/
                ShowMoreContact(result);
            },
            error: function (XMLHttpRequest, textStatus, errorThrown)
            {
                alert("调用失败!可能是服务提供商不允许 Ajax 来调用!");
            }
        });
    }
    function invoke4()
    {
        showOrHideDiv("divInvoke4");
    }
    function invoke4Core()
    {
        var contact = new Object();
        contact.Id = $.trim($("#txtInvoke4_Id").val());
        contact.FirstName = $.trim($("#txtInvoke4_FirstName").val());
        contact.LastName = $.trim($("#txtInvoke4_LastName").val());
        contact.PhoneNo = $.trim($("#txtInvoke4_PhoneNo").val());
        contact.EmailAddress = $.trim($("#txtInvoke4_EmailAddress").val());
        $.ajax({
            type: "POST",   //访问WebService必须使用Post方式请求
            url: baseUrl + "Add", //调用WebService的地址和方法名称组合 ---- WsURL/方法名  
            dataType: 'xml',
            data: contact,
            success: function (result)
            {
                //响应的类型为 xml,结构为:
                /*
                <?xml version="1.0" encoding="utf-8"?>
                <string xmlns="http://tempuri.org/">1</string>
                */
                alert($(result).text());
            },
            error: function (XMLHttpRequest, textStatus, errorThrown)
            {
                alert("调用失败!可能是服务提供商不允许 Ajax 来调用!");
            }
        });
    }
    function invoke5()
    {
        showOrHideDiv("divInvoke5");
    }
    function invoke5Core()
    {
        var id = $.trim($("#txtInvoke5_Id").val());
        $.ajax({
            type: "POST",   //访问WebService必须使用Post方式请求
            url: baseUrl + "Delete", //调用WebService的地址和方法名称组合 ---- WsURL/方法名  
            dataType: 'xml',
            data: { id: id },
            success: function (result)
            {
                //如果有数据,响应的类型为 xml,结构为:
                /*
                <?xml version="1.0" encoding="utf-8"?>
                <string xmlns="http://tempuri.org/">1</string>
                */
                alert($(result).text());
            },
            error: function (XMLHttpRequest, textStatus, errorThrown)
            {
                alert("调用失败!可能是服务提供商不允许 Ajax 来调用!");
            }
        });
    }
    function invoke6()
    {
        $.ajax({
            type: "GET",   //访问WebService必须使用Post方式请求
            url: "/NewsApi/HelloWorld", //调用WebService的地址和方法名称组合 ---- WsURL/方法名  
            dataType: 'jsonp',
            jsonp: 'p',
            success: function (result)
            {
                alert(result);
            },
            error: function (XMLHttpRequest, textStatus, errorThrown)
            {
                alert("调用失败!可能是服务提供商不允许 Ajax 来调用!");
            }
        });
    }
</script>

3. 新建一个 Controller,为跨域调用提供接口。

    public class NewsApiController : Controller
    {
        //
        // GET: /NewsApi/

        public ActionResult Index()
        {
            return View();
        }

        public ActionResult HelloWorld(string p)
        {
            NewsService service = new NewsService();
            return JavaScript("" + p + "(\""+ service.HelloWorld() + ", 服务器时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") +"\");");
        }
    }

4. 在 Web.Config 中配置如下:

  <system.web>
    <!-- 特别注意要增加的 -->
    <webServices>
      <protocols>
        <add name="HttpGet"/>
        <add name="HttpPost"/>
      </protocols>
    </webServices>
   </system.web>

5. 部署 Web Service。


如果只是在本地测试,另外新建一个项目即可,如果是上线项目,那么最好是部署在 IIS 上。我这里就在 VS 开发服务器中部署了。


6. 跨项目调用。


第一小步:添加服务引用。

省略。


第二小步:添加服务引用后,查看 Web.Config 文件。生成的代码如下:

<?xml version="1.0" encoding="utf-8"?>

<!--
  有关如何配置 ASP.NET 应用程序的详细消息,请访问
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->

<configuration>
    <system.web>
        <compilation debug="true" targetFramework="4.0" />
    </system.web>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="NewsServiceSoap" closeTimeout="00:01:00" openTimeout="00:01:00"
                    receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
                    bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                    messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                    useDefaultWebProxy="true">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                    <security mode="None">
                        <transport clientCredentialType="None" proxyCredentialType="None"
                            realm="" />
                        <message clientCredentialType="UserName" algorithmSuite="Default" />
                    </security>
                </binding>
            </basicHttpBinding>
            <customBinding>
                <binding name="NewsServiceSoap12">
                    <textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
                        messageVersion="Soap12" writeEncoding="utf-8">
                        <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                            maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                    </textMessageEncoding>
                    <httpTransport manualAddressing="false" maxBufferPoolSize="524288"
                        maxReceivedMessageSize="65536" allowCookies="false" authenticationScheme="Anonymous"
                        bypassProxyOnLocal="false" decompressionEnabled="true" hostNameComparisonMode="StrongWildcard"
                        keepAliveEnabled="true" maxBufferSize="65536" proxyAuthenticationScheme="Anonymous"
                        realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false"
                        useDefaultWebProxy="true" />
                </binding>
            </customBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:3984/api/NewsService.asmx"
                binding="basicHttpBinding" bindingConfiguration="NewsServiceSoap"
                contract="NewsWebServiceReference.NewsServiceSoap" name="NewsServiceSoap" />
            <!--<endpoint address="http://localhost:3984/api/NewsService.asmx"
                binding="customBinding" bindingConfiguration="NewsServiceSoap12"
                contract="NewsWebServiceReference.NewsServiceSoap" name="NewsServiceSoap12" />-->
        </client>
    </system.serviceModel>
</configuration>

说明:由于添加 Web 引用后, Web.Config 中的 system.serviceModel > client 下会生成 2 个 endpoint 子节点,需要删除一个。否则运行时,会抛出异常!


第三小步:新建一个 aspx 页面。服务器端调用。


前台代码如下:

    <form id="form1" runat="server">
    <br /><br />
    <div>
        <a href="jqueryInvokeWebService.htm">JQuery 调用 WebService</a><br /><br />
    </div>
    <br /><br />
    <div>
        <asp:Button ID="btnAdd" runat="server" Text="添加" OnClick="btnAdd_Click" />
    </div>
    <br /><br /><br />
    <div>
        <asp:GridView ID="gvList" runat="server" EnableViewState="false">
        </asp:GridView>
    </div>
    </form>

后台代码如下:

    public partial class NewsIndex : System.Web.UI.Page
    {
        private static NewsServiceSoapClient _soapClient;

        protected static NewsServiceSoapClient SoapClient
        {
            get
            {
                if (_soapClient == null)
                {
                    _soapClient = new NewsServiceSoapClient();
                }
                return _soapClient;
            }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if(!IsPostBack)
            {
                InitData();
                //Response.Write(SoapClient.Endpoint.Address); // 获取 Web Service 的路径 Url: http://localhost:3984/api/NewsService.asmx 
            }
        }

        private void InitData()
        {
            BindData(SoapClient.Get());
        }

        private void BindData(IEnumerable<Contact> items)
        {
            this.gvList.DataSource = items;
            this.gvList.DataBind();
        }

        protected void btnAdd_Click(object sender, EventArgs e)
        {
            Contact c = new Contact();
            c.Id = Guid.NewGuid().ToString().Replace("-", "_");
            c.FirstName = "张三" + c.Id;
            c.LastName = "最棒" + c.Id;
            c.PhoneNo = "138-8888-8888";
            c.EmailAddress = "zhangsan@DearBruce.com";

            string addResult;

            Random random = new Random();
            int randomNum = random.Next(1, 11); // 返回结果是 1-10
            if (randomNum > 5)
            {
                addResult = SoapClient.AddContact(c);
            }
            else
            {
                addResult = SoapClient.Add(c.FirstName, c.LastName, c.PhoneNo, c.EmailAddress, c.Id);
            }
            ShowMessage(addResult);
            InitData();
        }
        
    }

第四小步:新建一个 html 页面。客户端调用。


省略。代码和上面的代码相同。其中跨域调用的代码如下:

<input type="button" value="JSONP 跨域调用 HelloWorld" onclick="invoke6();" /><br />

<script type="text/javascript">
    function invoke6()
    {
        $.ajax({
            type: "GET",   //访问WebService必须使用Post方式请求
            url: baseJsonpUrl + "HelloWorld", //调用WebService的地址和方法名称组合 ---- WsURL/方法名  
            dataType: 'jsonp',
            jsonp: 'p',
            success: function (result)
            {
                alert(result);
            },
            error: function (XMLHttpRequest, textStatus, errorThrown)
            {
                alert("调用失败!可能是服务提供商不允许 Ajax 来调用!");
            }
        });
    }
</script>

 

 

谢谢浏览!