WCF 第十三章 可编程站点 使用WebOperationContext
2011-06-09 06:37 DanielWise 阅读(4046) 评论(1) 编辑 收藏 举报寄宿服务使用WebHttpinding绑定来读或者写HTTP上下文是很常见的。这可以使用WebOperationContext类实现。有很多理由来访问HTTP上下文。你可能想要读取自定义的认证信息头或授权信息头,控制缓存或者设置内容类型,例如。
图片13.3 显示了一个在当前计算机上显示墙纸的网络应用程序。整个应用程序是使用一个WCF服务创建的而且可以使用网络浏览器访问。

图片13.3 墙纸网络应用程序
图片13.12显示了WallpaperService服务的代码。有一个在一个HTML页上显示所有图片的Images操作。这个操作设置ContextType头以便于浏览器可以将输入理解成HTML。它也设置了Cache-Control头以便于额外的图片可以添加到应用程序中而不用浏览器缓存图像。最后,有一个将一个图像返回给浏览器的Image操作。这个操作设置ContextType和ETag头。
注意 从REST中获得.svc WCF服务使用.svc扩展在IIS中寄宿。这和常见的REST URI 命名经验不同。例如,列表13.12中的服务使如下URI访问:http://localhost/Wallpaper/WallpaperService.svc/images 你可以通过使用一个ASP.NET HttpModule(仅IIS 7.0)调用HttpContext.RewritePath去修改URI来移除.svc扩展名。这将允许URI采用下面格式: http://localhost/Wallpaper/WallpaperService/images |
列表13.12 Wallpaper图片服务
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.ServiceModel.Web; using System.Text; using System.ServiceModel.Activation; using System.Web; using System.IO; using System.Web.UI; namespace EssentialWCF.WallpaperImage { // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together. [ServiceContract] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] public class WallpaperService { private static UriTemplate ImageUriTemplate = new UriTemplate( "/image/{name}" ); private string ImagePath { get { return @"C:\Windows\Web\Wallpaper" ; } } private Image GetImage( string name, Uri baseUri) { return new Image(name, ImageUriTemplate.BindByPosition(baseUri, new string [] { name })); } private void PopulateListOfImages(List<Image> list, Uri baseUri) { HttpContext ctx = HttpContext.Current; ; DirectoryInfo d = new DirectoryInfo(ImagePath); FileInfo[] files = d.GetFiles( "*.jpg" ); foreach (FileInfo f in files) { string fileName = f.Name.Split( new char [] { '.' })[0]; string etag = fileName + "_" + f.LastWriteTime.ToString(); list.Add(GetImage(fileName, baseUri)); } } [OperationContract] [WebGet(UriTemplate = "/images" )] public void Images() { WebOperationContext wctx = WebOperationContext.Current; ; wctx.OutgoingResponse.ContentType = "text/html" ; wctx.OutgoingResponse.Headers.Add( "Cache-Control" , "no-cache" ); Uri baseUri = wctx.IncomingRequest.UriTemplateMatch.BaseUri; List<Image> listOfImages = new List<Image>(); PopulateListOfImages(listOfImages, baseUri); TextWriter sw = new StringWriter(); ; Html32TextWriter htmlWriter = new Html32TextWriter(sw); htmlWriter.WriteFullBeginTag( "HTML" ); htmlWriter.WriteFullBeginTag( "BODY" ); htmlWriter.WriteFullBeginTag( "H1" ); htmlWriter.Write( "wallpaper" ); htmlWriter.WriteEndTag( "H1" ); htmlWriter.WriteFullBeginTag( "TABLE" ); htmlWriter.WriteFullBeginTag( "TR" ); int i = 0; Image image; while (i < listOfImages.Count) { image = listOfImages[i]; htmlWriter.WriteFullBeginTag( "TD" ); htmlWriter.Write(image.Name); htmlWriter.WriteBreak(); htmlWriter.WriteBeginTag( "IMG" ); htmlWriter.WriteAttribute( "SRC" , image.Uri); htmlWriter.WriteAttribute( "STYLE" , "width:150px;height:150px" ); htmlWriter.WriteEndTag( "IMG" ); htmlWriter.WriteEndTag( "TD" ); if (((i + 1) % 5) == 0) { htmlWriter.WriteEndTag( "TR" ); htmlWriter.WriteFullBeginTag( "TR" ); } i++; } htmlWriter.WriteEndTag( "TR" ); htmlWriter.WriteEndTag( "TABLE" ); htmlWriter.WriteEndTag( "BODY" ); htmlWriter.WriteEndTag( "HTML" ); HttpContext ctx = HttpContext.Current; ctx.Response.Write(sw.ToString()); } [OperationContract] [WebGet(UriTemplate = "/image/{name}" )] public void GetImage( string name) { WebOperationContext wctx = WebOperationContext.Current; wctx.OutgoingResponse.ContentType = "image/jpeg" ; HttpContext ctx = HttpContext.Current; string fileName = null ; byte [] fileBytes = null ; try { fileName = string .Format( @"{0}\{1}.jpg" , ImagePath, name); if (File.Exists(fileName)) { using (FileStream fs = File.OpenRead(fileName)) { fileBytes = new byte [fs.Length]; fs.Read(fileBytes, 0, Convert.ToInt32(fs.Length)); } } else { wctx.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.NotFound; } } catch { wctx.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.NotFound; } FileInfo fi = new FileInfo(fileName); wctx.OutgoingResponse.ETag = fileName + "_" + fi.LastWriteTime.ToString(); ctx.Response.OutputStream.Write(fileBytes, 0, fileBytes.Length); } } // Use a data contract as illustrated in the sample below to add composite types to service operations. [DataContract] public class Image { string name; string uri; public Image() { } public Image( string name, string uri) { this .name = name; this .uri = uri; } public Image( string name, Uri uri) { this .name = name; this .uri = uri.ToString(); } [DataMember] public string Name { get { return this .name; } set { this .name = value; } } [DataMember] public string Uri { get { return this .uri; } set { this .uri = value; } } } } |
下面列表13.13中的配置用来寄宿WallpaperService服务。服务使用WebHttpBinding绑定和WebHttpBehavior终结点行为来寄宿。
列表13.13 Wallpaper图像服务配置
< system.serviceModel > < serviceHostingEnvironment aspNetCompatibilityEnabled="true"/> < services > < service name="EssentialWCF.WallpaperImage.WallpaperService" behaviorConfiguration="MetadataBehavior"> < endpoint address="" behaviorConfiguration="WebBehavior" binding="webHttpBinding" contract="EssentialWCF.WallpaperImage.WallpaperService"/> < endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> </ service > </ services > < behaviors > < endpointBehaviors > < behavior name="WebBehavior"> < webHttp /> </ behavior > </ endpointBehaviors > < serviceBehaviors > < behavior name="MetadataBehavior"> < serviceMetadata httpGetEnabled="true" httpGetUrl=""/> < serviceDebug includeExceptionDetailInFaults="true"/> </ behavior > </ serviceBehaviors > </ behaviors > </ system.serviceModel > |
列表13.14 显示了用来在IIS中寄宿WallpaperService的.svc文件。
列表13.14 WallpaperService.svc
<%@ ServiceHost Language= "C#" Debug= "true" Service= "EssentialWCF.WallpaperImage.WallpaperService" CodeBehind= "~/App_Code/WallpaperImageService.cs" %> |
作者:DanielWise
出处:http://www.cnblogs.com/danielWise/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述