構建WCF RESTful service示例
REST架構遵循了CRUD原則,即四種行為:Create, Read, Update, Delete. 通過這四種行為完成一般的操作和處理,並且可以通過結合這些操作完成複雜的service結構。REST架構讓我們可以更加深入的瞭解HTTP協議, 針對於協議的程式設計,更有利於開發出伸縮性強的應用。
REST將網路上的所有事物都抽象為資源,並通過聯結器介面對資源進行CRUD的操作。
好,閒話少說,通過一個例子來說明RESTful service的構建和呼叫方式。
這個例子是關於圖片的一個例子,說明我們怎樣通過service來上傳圖片,和瀏覽圖片,並且通過service將我們的local資源可以上載的網路中,節省空間。當然根據你的需要,可以把程式碼改變為自己的應用程式的邏輯程式碼。
為了證明這個service的可用性 我們需要建立兩個project來完成這個專案,一個為Server,另一個為Client,Client端負責通過service與Service端互動,所以service應該部署在Server端的Web application中。
[本示例完整原始碼下載(0分)] http://download.csdn.net/detail/aa466564931/3867365
建立PictureRESTService.cs類 並且通過下載Web API來建立這個service, 這裡的Web API是微軟開發的一套幫助我們建立和使用RESTful service的工具,大家可以在這裡下載,並且引用在專案中,注意這些API有相互引用的地方所以建議大家在引用時候全部加入引用。
[最新的版本 WCF Web API Preview 5] http://wcf.codeplex.com/releases/view/73399
引用例子: using Microsoft.ApplicationServer.Http;
PictureRESTService.cs
namespace CSWCFPhotoRatingSystem
{
/// <summary>
/// The RESTful web service that used to handle image basic functions.
/// </summary>
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall, Namespace="PictureService")]
public class PictureRESTService
{
/// <summary>
/// Images search service.
/// </summary>
/// <param name="image"></param>
/// <returns></returns>
[WebGet(UriTemplate="/{image}")]
public HttpResponseMessage GetImages(string image)
{
var response = new HttpResponseMessage();
Stream memory = new MemoryStream();
memory = GetImageByName(image);
memory.Position = 0;
response.Content = new StreamContent(memory);
response.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");
return response;
}
/// <summary>
/// Image adding service.
/// </summary>
/// <param name="message"></param>
/// <param name="image"></param>
[WebInvoke(UriTemplate = "/{image}", Method = "POST")]
public void AddImages(HttpRequestMessage message,string image)
{
var directory = System.Web.HttpContext.Current.Server.MapPath("~/Images");
var file = Path.Combine(directory, image);
Stream stream = message.Content.ContentReadStream;
FileStream fileStream = File.Create(System.Web.HttpContext.Current.Server.MapPath("~/Image/") + image);
stream.CopyTo(fileStream);
stream.Close();
fileStream.Close();
this.XmlFileAppend(image, System.Web.HttpContext.Current.Server.MapPath("~/Image/") + image);
}
/// <summary>
/// Images information searching service.
/// </summary>
/// <returns></returns>
[WebGet(UriTemplate="",ResponseFormat=WebMessageFormat.Json)]
public List<string> GetImageList()
{
List<string> list = this.GetAllImages();
if (list != null && list.Count != 0)
{
return list;
}
else
{
return null;
}
}
/// <summary>
/// Get specify image by image's Name property.
/// </summary>
/// <param name="image"></param>
/// <returns></returns>
public Stream GetImageByName(string image)
{
XDocument document = XDocument.Load(System.Web.HttpContext.Current.Server.MapPath("~/App_Data/Photo.xml"));
var nodeList = from node in document.Descendants("Image")
where node.Attribute("open").Value.ToString().Equals("1")
select node;
foreach (var node in nodeList)
{
if (node.Element("Name").Value.Equals(image))
{
FileStream fileStream = null;
string physicUrl = node.Element("PhysicsUrl").Value;
fileStream = File.Open(physicUrl, FileMode.Open);
MemoryStream ms = new MemoryStream();
fileStream.CopyTo(ms);
return ms;
}
}
return null;
}
/// <summary>
/// Get all images' physics url string variable.
/// </summary>
/// <returns></returns>
public List<string> GetAllImages()
{
List<string> list = new List<string>();
XDocument document = XDocument.Load(System.Web.HttpContext.Current.Server.MapPath("~/App_Data/Photo.xml"));
var nodeList = from node in document.Descendants("Image")
where node.Attribute("open").Value.ToString().Equals("1")
select node;
foreach (var node in nodeList)
{
list.Add(node.Element("PhysicsUrl").Value);
}
return list;
}
/// <summary>
/// Add XElement to xml file to record new images.
/// </summary>
/// <param name="fileName"></param>
/// <param name="physicsUrl"></param>
protected void XmlFileAppend(string fileName, string physicsUrl)
{
string xmlPath = System.Web.HttpContext.Current.Server.MapPath("~/App_Data/Photo.xml");
XDocument document = XDocument.Load(xmlPath);
XElement element = new XElement("Image", new XElement("Name", fileName), new XElement("PhysicsUrl", physicsUrl));
element.Add(new XAttribute("open", "1"));
document.Element("Root").Add(element);
document.Save(xmlPath);
}
}
這裡通過Get方式獲取image 和所有image資訊列表,通過Post方式上傳image到server,並且把路徑和名稱等資訊通過XDocument儲存在xml檔案中,xml的檔案格式是這樣的
<?xml version="1.0" encoding="utf-8"?>
<Root>
<Image open="1">
<Name>a9ba816042594d108c6e597dbfbcd784.jpg</Name>
<PhysicsUrl>D:\Program1\Sample-code\WCFPhotoRatingSystem\Visual Studio 2010\CSWCFPhotoRatingSystem\CSWCFPhotoRatingSystem\Image\a9ba816042594d108c6e597dbfbcd784.jpg</PhysicsUrl>
</Image>
</Root>
同時我們需要在Global.ascx檔案的Application_Start方法中加入Url Routing的內容,以及上傳的Stream的大小調整,如果不做調整預設為65K左右。目前我測試的尺寸可以達到3Mb的圖片.
Global.asax.cs
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.SetDefaultHttpConfiguration(new WebApiConfiguration()
{
MaxReceivedMessageSize = int.MaxValue,
MaxBufferSize = int.MaxValue,
EnableTestClient = true
});
RouteTable.Routes.MapServiceRoute<PictureRESTService>("images");
}
部署完成後你可以根據localhost+port+images+imageName直接訪問你的圖片,前提是你必須要在image中已有圖片並且xml檔案有你的註冊資訊。
url示例:http://localhost:20242/images/a9ba816042594d108c6e597dbfbcd784.jpg
接下我們開始部署客戶端的程式碼,需要兩個頁面Default和UploadImage,Default用於顯示效果,Upload用於上傳。這裡我們在Upadload前臺頁面穿件有個FileUpload控制元件和一個按鈕(Button),fileUpload id為fupImageUpload。 並且附加一個Default頁面連結 方便你上傳完成後直接redirect到Default頁面。
/// <summary>
/// Upload button click event.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnUoload_Click(object sender, EventArgs e)
{
if (!fupImageUpload.HasFile)
{
Response.Write("Please choose a image.");
}
else
{
string fileName = fupImageUpload.FileName;
string fileExtension = Path.GetExtension(fileName).ToLower();
if (fileExtension.Equals(".jpg") || fileExtension.Equals(".gif") || fileExtension.Equals(".bmp"))
{
string randomName = Guid.NewGuid().ToString().Replace("-", "");
string newFileName = String.Concat(randomName, fileExtension);
string url = string.Format(serverUrl, newFileName);
WebRequest request = WebRequest.Create(url);
request.Method = "POST";
Stream stream = request.GetRequestStream();
(fupImageUpload.PostedFile.InputStream).CopyTo(stream);
request.GetResponse();
Response.Write(newFileName+" upload success.");
}
else
{
Response.Write("The file extension name is incorrect, we only support for these images type now(jpg, gif, bmp). ");
}
}
}
這裡通過WebRequest 方式呼叫RESTful service的AddImages方法,特別指定了埠,大家可能需要改變為你的server程式開啟的埠。其中serverUrl為常量,const string serverUrl = "http://localhost:48508/images/{0}"; 你當然可以把它放在config檔案中,便於修改。
接下來是Default頁面,這塊是我用JavaScript給出了一個Ajax SlideShow的效果,並且支援Zoom in(放大),這塊不是這個示例的重點,大家可以下載原始碼看看效果。
其中後臺是呼叫Service的GetImageList的方式獲取所有圖片的資訊,再通過JavaScript顯示出來,為了達到更好的展示效果,最好上傳兩張或兩張以上的圖片.
Default.aspx.cs
/// <summary>
/// The page is used to show the images and zoom in effect.
/// </summary>
public partial class Default : System.Web.UI.Page
{
public string ulConstruct = string.Empty;
const string serverUrl = "http://localhost:48508/images/";
WebRequest request = WebRequest.Create(serverUrl);
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
this.GetResult();
}
}
/// <summary>
/// Get images from PictureRESTService.
/// </summary>
public void GetResult()
{
WebResponse response = request.GetResponse();
HttpWebResponse webResponse = response as HttpWebResponse;
XDocument document;
if (webResponse.StatusCode.Equals(HttpStatusCode.OK))
{
using (StreamReader reader = new StreamReader(webResponse.GetResponseStream(),Encoding.GetEncoding("utf-8")))
{
document = XDocument.Load(reader);
}
var nodeList = from node in document.Descendants("string")
select node;
StringBuilder builder = new StringBuilder();
int i= 0;
foreach (var node in nodeList)
{
string fileName = node.Value.Substring(node.Value.ToString().LastIndexOf("\\") + 1);
i++;
builder.Append("<li>");
builder.Append("<img src=\"");
builder.Append(String.Concat(serverUrl, fileName));
builder.Append("\" alt=\"");
builder.Append(fileName);
builder.Append("\" onclick=\"hidediv('");
builder.Append(String.Concat(serverUrl, fileName));
builder.Append("');\" />");
builder.Append("</li>");
}
if (i.Equals(0))
{
Response.Write("Please upload some images for viewing.");
lbMessage.Text = "";
}
else
{
ulConstruct = builder.ToString();
lbMessage.Text = "Big format:";
}
}
else
{
Response.Write("Web request failed.");
}
}
}
好了 這裡有一個ulConstruct的string變數,用於顯示HTML的code在Default.aspx資訊,大家可以看看下載檔案中的HTML頁面的詳細資訊,這裡就不列舉這些前臺頁面的程式碼了。
如果一切順利的話,就可以debug了。
如果在開發中看到遠端服務錯誤或者是400, 500的錯誤的話,關注下你的配置檔案和程式碼是否正確,get方式的話你可以直接將連結放在瀏覽器中進行測試,判斷問題是出現在service上還是配置上。
Ok.
相關文章
- 利用WCF建立簡單的RESTFul ServiceREST
- 構建一個基於 Spring 的 RESTful Web ServiceSpringRESTWeb
- 在IIS8.5的環境下配置WCF的Restful ServiceREST
- WCF Rest ServiceREST
- 構建高效能分散式搜尋引擎(Wcf-示例篇)三薦分散式
- 通過配置web.config使WCF向外提供HTTPS的Restful ServiceWebHTTPREST
- flask-restful 大型專案結構示例FlaskREST
- RESTful Web Service(續)RESTWeb
- WCF、Web API、WCF REST、Web Service之區別WebAPIREST
- 什麼是web service?- SOAP Web Service & Restful Web ServiceWebREST
- spring boot構建restful服務Spring BootREST
- 使用Golang和MongoDB構建 RESTful APIGolangMongoDBRESTAPI
- 使用Swashbuckle構建RESTful風格文件REST
- WCF Security:Silverlight authentication for WCF service based on security token
- 構建oracle function的小示例OracleFunction
- 使用 .NET Core 3.x 構建 RESTFUL ApiRESTAPI
- Spring Boot 構建 Restful API 和測試Spring BootRESTAPI
- 使用ASP.NET Web API構建RESTful APIASP.NETWebAPIREST
- Spring Boot實戰:Restful API的構建Spring BootRESTAPI
- c# tcbs之建構函式呼叫建構函式示例C#函式
- Qt構建與解析Json示例QTJSON
- 使用 .NET Core 3.x 構建 RESTFUL Api (續)RESTAPI
- WCF、Net remoting、Web service概念及區別REMWeb
- 基於 Spring Boot 2.0 構建一個 RESTful WebServiceSpring BootRESTWeb
- springmvc+swagger構建Restful風格文件SpringMVCSwaggerREST
- 使用 Jersey 和 Apache Tomcat 構建 RESTful Web 服務ApacheTomcatRESTWeb
- CXF+Spring+JAXB+Json構建Restful服務SpringJSONREST
- 使用 Python 構建一個簡單的 RESTful APIPythonRESTAPI
- WCF 的 Service Instance模式和併發處理模式
- 使用maven構建java9 service例項MavenJava
- [實戰] 使用 MongoDB Go 驅動與 Iris 構建 RESTful APIMongoDBRESTAPI
- springcloud架構-HongHucommon-service專案構建過程SpringGCCloud架構
- 為 Memcached 構建基於 Go 的 Operator 示例Go
- Golang如何快速構建一個CLI小工示例Golang
- 測試必須學spring RESTful Service(上)SpringREST
- 測試必須學 spring RESTful Service (上)SpringREST
- A Simple RESTful API Service With Node.js And Koa2RESTAPINode.js
- 理解RESTFul架構REST架構