構建 RESTful 服務
1.設計須知
- 您需要什麼樣的資源?
- 將使用哪些 URI 表示這些資源?
- 每個 URI 將支援統一介面的哪些部件(HTTP 動詞)
2.下面設計uri
3.建立一個wcf工程StudentService,刪除裏面的所有代碼
3.1 建立一些使用到的類 IssuesCollection
public class IssuesCollection { public string SchoolName { get; set; } public List<IssuesData> IssuesDatas; }
public class IssuesData { public string Issues { set; get; } public int Year { set; get; } }
public class Student { public int ID { get; set; } public string Name { get; set; } public Nullable<int> Score { get; set; } public string State { get; set; } } public class Department { public string SchoolName { get; set; } public string DepartmentName { get; set; } public List<Student> Students { get; set; } }
3.2 建立Service類,主要處理類
[ServiceContract] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] public class Service { [OperationContract] [WebGet(UriTemplate = "/")] public IssuesCollection GetAllIssues() { //Iniissues(); //return issues; IssuesCollection issues1 = new IssuesCollection(); issues1.SchoolName = "gsw"; issues1.IssuesDatas = new List<IssuesData>(); for (int i = 0; i < 10; i++) { IssuesData item = new IssuesData() { Issues = "gsw" + i.ToString(), Year = 2010 + i }; issues1.IssuesDatas.Add(item); } return issues1; } [OperationContract] [WebGet(UriTemplate = "Service/GetDepartment")] public Department GetDepartment() { Department department = new Department { SchoolName = "北京大學", DepartmentName = "學生處", Students = new List<Student>() }; return department; } [OperationContract] [WebGet(UriTemplate = "Service/GetAStudent({id})")] public Student GetAStudent(string id) { Random rd = new Random(); Student aStudent = new Student { ID = System.Convert.ToInt16(id), Name = "Name No. " + id, Score = Convert.ToInt16(60 + rd.NextDouble() * 40), State = "GA" }; return aStudent; } [OperationContract] [WebInvoke(Method ="POST", UriTemplate = "Service/AddStudentToDepartment", BodyStyle = WebMessageBodyStyle.WrappedRequest)] public Department AddStudentToDepartment(Department department, Student student) { List<Student> Students = department.Students; Students.Add(student); return department; } }
3.3 設置配置文件web.config
<?xml version="1.0"?> <configuration> <system.web> <compilation debug="true" targetFramework="4.0" /> </system.web> <system.serviceModel> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> <standardEndpoints> <webHttpEndpoint> <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true" /> </webHttpEndpoint> </standardEndpoints> </system.serviceModel> <system.webServer> <modules runAllManagedModulesForAllRequests="true"/> </system.webServer> </configuration>
3.4 在Global.asax 中加入事件
public class Global : System.Web.HttpApplication { protected void Application_Start(object sender, EventArgs e) { RouteTable.Routes.Add(new ServiceRoute("", new WebServiceHostFactory(), typeof(Service))); } protected void Application_BeginRequest(object sender, EventArgs e) { HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache); HttpContext.Current.Response.Cache.SetNoStore(); EnableCrossDmainAjaxCall(); } private void EnableCrossDmainAjaxCall() { HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*"); if (HttpContext.Current.Request.HttpMethod == "OPTIONS") { 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 rest,可以測試使用。運行工程http://localhost:4305/help,介面如下:
和我們上面設置的資源是一樣的。
4.代碼解讀
4.1 [ServiceContract] 定義服務
4.2 [WebGet(UriTemplate = "/")] ,使用網站根路徑,得到相應內容,基本是get方法。
我們輸入 http://localhost:4305/,頁面會輸出
gsw02010gsw12011gsw22012gsw32013gsw42014gsw52015gsw62016gsw72017gsw82018gsw92019gsw
這個正好是GetAllIssues方法返回的內容。
http://localhost:4305/Service/GetDepartment,會顯示 學生處北京大學
4.3 UriTemplate 指定uri。
4.4 WebGetAttribute 告訴調度程式方法應該回應 HTTP GET 請求。 WebInvokeAttribute 預設映射為 HTTP POST,但可將 WebInvokeAttribute.Method 屬性設置為支援所有其他 HTTP 動詞(PUT 和 DELETE 是最常用的兩個)。 URI 預設由方法的名稱確定(添加到端點的基礎 URI 之上)。
4.5 可以指定輸出類型
5. 客戶端調用
5.1 代碼調用
5.1.1 get 語句
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://localhost:4305/Service/GetDepartment"); HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(Department)); object o = json.ReadObject(resp.GetResponseStream()); Department d = (Department)o;
5.1.2 post 語句
修改服務器端uri,這個方法,只是提交Department,返回Department類型,並且設置
department.SchoolName = "test";
[OperationContract] [WebInvoke(Method ="POST", UriTemplate = "Service/AddStudentToDepartment", RequestFormat = WebMessageFormat.Json,BodyStyle = WebMessageBodyStyle.Bare ,ResponseFormat=WebMessageFormat.Json)] public Department AddStudentToDepartment(Department department) { //List<Student> Students = department.Students; //Students.Add(student); department.SchoolName = "test"; return department; }
客戶端調用:
WebClient clent = new WebClient(); Department department = new Department(); department.DepartmentName = "學生會"; department.SchoolName = "天津大學"; department.Students = new List<Student>(); department.Students.Add(new Student() { ID = 12, Name = "gsw", Score = 34, State = "查" }); MemoryStream ms = new MemoryStream(); DataContractJsonSerializer serializerToupdata = new DataContractJsonSerializer(typeof(Department)); serializerToupdata.WriteObject(ms, department); clent.Headers["Content-type"] = "application/json"; //提交數據,並且返回數據 byte[] bytes= clent.UploadData("http://localhost:4305/Service/AddStudentToDepartment", "POST", ms.ToArray()); ms = new MemoryStream(bytes); serializerToupdata = new DataContractJsonSerializer(typeof(Department)); object o = serializerToupdata.ReadObject(ms); Department d = (Department)o;
最好的到的d對象,SchoolName是“test”,說明提交成功,讀取成功。
5.2 jquery調用
<script type="text/javascript"> $(document).ready(function () { $.ajax({ cache: false, type: "GET", async: false, dataType: "json", url: "http://localhost:4305/", success: function (department1) { //返回名稱 alert(department1.SchoolName); }, error: function (xhr) { alert(xhr.responseText); } }); }); </script>
調用 http://localhost:4305/方法,返回IssuesCollection類型,輸出 alert(department1.SchoolName);