ASP.NET MVC 4 小项目开发总结
ASP.NET MVC 4 小项目开发总结
项目很小,就是一个企业站的前后台,主要包括新闻模块、产品模块、视频模块、留言。没有什么技术上的难点,大部分就是CRUD操作。开始之前评估开发时间为4天,实际coding时间为3天,debug时间为2天,关于debug时间较长的问题,后面有较为详细的分析。
所用技术和工具 Visual Studio 2012 ASP.NET MVC 4 Entify Framework 5 Sqlite Uploadify
关于ASP.NET MVC 4
相比MVC 3,个人感觉并没有太大的变化,也许是一些新特性没有用到。
debug花费时间分析
除开没有后台页面等其他因素,自身原因分析如下:
拿到需求后没有进行较为详细的确认
虽然项目需求简单,但有些地方开始时疏于沟通,最终所省掉的时间还是用在了debug上,甚至更多。
浏览器兼容性问题
仅在开发阶段使用chrome浏览器,ie系也仅测试ie10,其余未考虑,后续在浏览器兼容性方面的调试花费了较多的时间。
例如如下的问题:
ie7下jquery.validate报错将 this.attr("novalidate", "novalidate"); 修改为: if (typeof (Worker) !== "undefined") { this.attr('novalidate', 'novalidate'); }
ie7下ckeditor的dialog加载iframe窗口高度不正常问题
尝试了很多网上的解决方案,均不管用,后来使用了一个非常规手段,就是给浏览器加上强制使用ie8模式的meta信息
ie8下jquery.validate不起作用
版本匹配问题:经测试:jquery-1.8.2 with jquery.validate-1.9正常
uploadify控件使用不是很熟练
很多api需要现查官方文档,而且官方站点还需FQ。同时在集成uploadify到ckeditor里面的时候,也花费了较多的时间,主要是用在查官方文档上面。这块写了较多的js代码,在后续浏览器兼容性方面调试也比较麻烦。
firefox下上传文件出现http error 302
网上大部分的情况是firefox和chrome同时出现此问题,基本都是说session的原因,但我的环境chrome却没有出问题。我的解决方案比较简单,就是对上传文件的后台action取消授权检查。应该还是跟session有关,更好的解决方案可查询谷歌。
Entity Framework sqlite数据源适配问题
主要是开始无法新建sqlite数据源,ef的设计器总是报错,无法通过数据库更新实体等。另外sqlite中文模糊查询问题。
设计器报错问题
需要到sqlite官网下载合适的数据源驱动程序 http://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki
sqlite中文字符串模糊查询问题
原来使用的方式:dbcontext.Post.Where(t=>t.Name.Contains(s)),对应的sql语句为charindex,改为:list = context.Database.SqlQuery(string.Format("select * from product where name like '%{0}%'",arcTitle)).AsQueryable();
版权声明 QiuLiang 所有文章遵循 创作共用版权协议 ,要求 署名、非商业、保持一致 。在满足 创作共用版权协议 的基础上可以转载,但请以超链接形式注明出处。
分类: MVC
WebService深入剖析
最近做WebService,最开始用weblogic自带的集成IDE---Eclipse做,,死活出不来,很惨很惨,然后换了个myeclipse8.6来整,使用Tom猫部署。
基于JAX-WS做,然后使用SOAP消息调用WebService。整了1个多小时,坑。。。
虽然关于HelloWorld的例子满天飞,但是今天还是从该出起,完整的记录点点滴滴。
整体工程:
步骤:
一:首先加入JAX-WS核心包:
Book类为实体类,包含基本的ID,名称之类的。
以其中的 UpdateBook 作为例子:
二:创建BookService接口:
@WebService @SOAPBinding(style = SOAPBinding.Style.RPC) public interface UpdateBook { public String update( int id1, int id2, String name); }三:创建BookService接口实现类:
@WebService(endpointInterface = "com.bfchuan.server.UpdateBook" ) public class UpdateBookImpl implements UpdateBook{ @Override public String update( int id1, int id2, String name) { if (id1==1&id2==2&name.equals("bfc" )){ return "SUCC" ; } else { return "Fail" ; } } }WebService为注解,该注解能设置很多选项:
- name wsdl:portType 的名称。缺省值为 Java 类或接口的非限定名称。(字符串)
- targetNamespace 指定从 Web Service 生成的 WSDL 和 XML 元素的 XML 名称空间。缺省值为从包含该 Web Service 的包名映射的名称空间。(字符串)
- serviceName 指定 Web Service 的服务名称: wsdl:service 。缺省值为 Java 类的简单名称 + Service 。(字符串)
- endpointInterface 指定用于定义服务的抽象 Web Service 约定的服务端点接口的限定名。如果指定了此限定名,那么会使用该服务端点接口来确定抽象 WSDL 约定。(字符串)
- portName wsdl:portName 。缺省值为 WebService.name+ Port 。(字符串)
- wsdlLocation 指定用于定义 Web Service 的 WSDL 文档的 Web 地址。Web 地址可以是相对路径或绝对路径。(字符串)
这些属性如果不设置,在WSDL里面会有默认值。当你每将一个类发布成服务的时候,就会有一个WSDL描述文件。
第四:增加WSDL文件,在该项目中,该文件如下:
<? xml version="1.0" encoding="UTF-8" ?> <!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.3-hudson-390-. --> < definitions xmlns ="http://schemas.xmlsoap.org/wsdl/" xmlns:soap ="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns ="http://server.bfchuan.com/" xmlns:wsu ="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:xsd ="http://www.w3.org/2001/XMLSchema" name ="UpdateBookImplService" targetNamespace ="http://server.bfchuan.com/" > < types /> < message name ="update" > < part name ="arg0" type ="xsd:int" /> < part name ="arg1" type ="xsd:int" /> < part name ="arg2" type ="xsd:string" /> </ message > < message name ="updateResponse" > < part name ="return" type ="xsd:string" /> </ message > < portType name ="UpdateBook" > < operation name ="update" parameterOrder ="arg0 arg1 arg2" > < input message ="tns:update" /> < output message ="tns:updateResponse" /> </ operation > </ portType > < binding name ="UpdateBookImplPortBinding" type ="tns:UpdateBook" > < soap:binding style ="rpc" transport ="http://schemas.xmlsoap.org/soap/http" /> < operation name ="update" > < soap:operation soapAction ="" /> < input > < soap:body namespace ="http://server.bfchuan.com/" use ="literal" /> </ input > < output > < soap:body namespace ="http://server.bfchuan.com/" use ="literal" /> </ output > </ operation > </ binding > < service name ="UpdateBookImplService" > < port binding ="tns:UpdateBookImplPortBinding" name ="UpdateBookImplPort" > < soap:address location ="http://localhost:8080/WebService/UpdateBookImplPort" /> </ port > </ service > </ definitions >现在为WSDL做一一的解析:
1.Type:
其中Type为空,为什么呢?
因为Type是用来导入和局部定义web服务交换信息要使用的XML Schema中的简单类型定义-------所有的Web服务将能够随时使用它们,因此,在这个项目中没有必要在这此处放入任何东西。通常来说,WSDL将Type定义成指向外部的schema。
举个例子,一个需要使用Type的格式如下所示:
< type > < xsd:Schema > < xsd:import namespace =http://soacookbook.com/ SchemaLocation-"http://localhost:7777/Test/HelloWSService?sxd =1"/> </xsd:Schema > </ type >2.Message
WSDL的Message部分包含请求和响应定义,与服务器通信时,要使用的这些请求和响应,你可能会注意到,请求和响应都是各自对应一条信息。请求信息与方法调用名称相同,因此此处采用的是RPC样式。响应名称是按照在操作后附加“Response”的方式给出的,这是JAX-WS的规范的默认方式。
对于请求:
< message name ="update" > < part name ="arg0" type ="xsd:int" /> < part name ="arg1" type ="xsd:int" /> < part name ="arg2" type ="xsd:string" /> </ message >每一个消息,都包含一个part子元素,消息part与方法中的参数类似,具有名称和类型。
第一个part的名称是 arg0 ,后面的以此类推,这个名字也是客户端调用的时候需要传递参数时候使用的名称(针对SOAP消息调用服务,后面会说到)
当然这些名称是系统默认的,你可以对它进行定制。
对于响应:
< message name ="updateResponse" > < part name ="return" type ="xsd:string" /> </ message >由于默认参数的样式纸是:wraped,Web服务返回值将封装在单个元素中,名称为 return ,你可以通过它提取剩余的载荷。
3.Binding
WSDL的 Binding 部分指定于服务器之间的消息传递方式。默认是SOAP,其他高级的选项包括HTTP,JSM,SMTP和TCP。由于通过对 UpdateBook 接口使用了这个注释:
@SOAPBinding(style = SOAPBinding.Style.RPC)指定希望将服务绑定带SOAP,因此会获得SOAP绑定作为消息传输方式
< soap:binding style ="rpc" transport ="http://schemas.xmlsoap.org/soap/http" />这里指定了一个地址,这意味着服务将使用SOAP1.1作为消息的发送和接受的协议。
还有个属性:style=“rpc”这个,该WSDL编写它是因为这个接口存在以上的那个注解。
4.Service
WSDL的Service部分指定服务名称将是 UpdateBookImplService 。该名称是在定义服务器的类名称后面加上Service的,这是JAX-WS在没有自定义名字的时候采用的默认命名。
这儿还指定使用SOAP绑定 UpdateBookImplPort 端口,端口命名也是默认,规则你懂的。
该部分带有SOAP的前缀,说明他们来自:"http://schemas.xmlsoap.org/wsdl/soap/"命名空间。
此处的Location属性指定可以在什么位置调用该服务,以及将使用哪些客户端来调用。
第五:创建sun-jaxws.xml文件,该文件如下所示:
<? xml version = "1.0" ?> < endpoints version ="2.0" xmlns ="http://java.sun.com/xml/ns/jax-ws/ri/runtime" > < endpoint name ="UpdateBookImplPort" implementation ="com.bfchuan.server.impl.UpdateBookImpl" url-pattern ="/UpdateBookImplPort" > </ endpoint > </ endpoints >该文件中,定义了该实现类的访问端口 UpdateBookImplPort ,即当访问该端口的时候,去找 com.bfchuan.server.impl.UpdateBookImpl 这儿。
第七:配置Web.xml文件
相信这个文件,都不陌生。该文件如下所示:
<? xml version="1.0" encoding="UTF-8" ?> < web-app version ="2.5" xmlns ="http://java.sun.com/xml/ns/javaee" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" > < servlet > < description > JAX-WS endpoint - HelloImplService </ description > < display-name > HelloImplService </ display-name > < servlet-name > HelloImplService </ servlet-name >
<!--配置监听---> < servlet-class > com.sun.xml.ws.transport.http.servlet.WSServlet </ servlet-class > < load-on-startup > 1 </ load-on-startup > </ servlet >
<!--这儿的UpdateBookImplPort就是对应 sun-jaxws.xml 中的UpdateBookImplPort,当访问这个UpdateBookImplPort的时候由
这儿转向 sun-jaxws.xml 的 UpdateBookImplPort ,再由 UpdateBookImplPort 去找实现类--> < servlet-mapping > < servlet-name > HelloImplService </ servlet-name > < url-pattern > /UpdateBookImplPort </ url-pattern > </ servlet-mapping >
< welcome-file-list > < welcome-file > index.jsp </ welcome-file > </ welcome-file-list > < listener > < listener-class > com.sun.xml.ws.transport.http.servlet.WSServletContextListener </ listener-class > </ listener ></ web-app >于是整个WebService的文件解析完了。
流程为:
首先web.xml接收到请求port的请求------然后在sun-jaxws.xml中找对应的port-----找到对应的实现类
为什么他能找到?WSDL在这儿起了管理作用,定义了相关信息,将某个port和某个service绑定在一起。
然后就是客户端。客户端我采用SOAP消息调用service的服务。
现在对SOAP的消息做一个介绍:
SOAP基于HTTP协议传输,(通常是这样,当然也可一使用JSM和其他机制)。合并防火墙通常允许交换已有HTTP流量,并使用适当机制来处理流量,包括防火墙规则,分支网络等。
SOAP被创建用来特定满足基于SOAP的WEB服务开发新手的需要,他可以手动操纵SOAP信封。关于SOAP信封的消息,度娘很多了。
下面基于该例子做一个基于SOAP消息调用服务:
一:首先创建一个java工程:
第二:创建一个文件,名字为:book.msg
内容为:
<? xml version="1.0" encoding="UTF-8" ?> < soap:Envelope xmlns:soap ="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd ="http://www.w3.org/2001/XMLSchema" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" > < soap:Body > < ns1:update xmlns:ns1 ="http://server.bfchuan.com/" > < arg0 > 3 </ arg0 > < arg1 > 3 </ arg1 > < arg2 > bfc </ arg2 > </ ns1:update > </ soap:Body > </ soap:HelloImpl >这儿的 arg0 分别对于WSDL里的那个参数,还记得吧。
这里的 update 对应WSDL里的操作数。
其他的为SOAP的消息体。
SOAP的消息载体写好了,现在我们需要发送消息。
第三:编写java类发送SOAP消息:
public class UpdateBook { public static void main(String[] args) { doSoapPost(); } public static void doSoapPost() { try { // First create the connection SOAPConnectionFactory soapConnFactory = SOAPConnectionFactory.newInstance(); SOAPConnection connection = soapConnFactory.createConnection(); // Next, create the actual message MessageFactory messageFactory = MessageFactory.newInstance(); SOAPMessage message = messageFactory.createMessage(); // Create objects for the message parts SOAPPart soapPart = message.getSOAPPart(); SOAPEnvelope envelope = soapPart.getEnvelope(); SOAPBody body = envelope.getBody(); // Populate the Message StreamSource preppedMsgSrc = new StreamSource( new FileInputStream("msg/updatebook.msg" )); soapPart.setContent(preppedMsgSrc); // Save the message message.saveChanges(); // Check the input System.out.println("/nREQUEST:/n" ); message.writeTo(System.out); System.out.println(); // Send the message and get a reply // Set the destination String destination = "http://localhost:8080/WebService/UpdateBookImplPort" ; // Send the message SOAPMessage reply = connection.call(message, destination); // Check the output System.out.println("/nRESPONSE:/n" ); // Create the transformer TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); // Extract the content of the reply Source sourceContent = reply.getSOAPPart().getContent(); // Set the output for the transformation StreamResult result = new StreamResult(System.out); transformer.transform(sourceContent, result); // Close the connection connection.close(); } catch (Exception e) { System.out.println(e.getMessage()); } } }对于该代码不做过多的说明,当该程序运行后,结果如下所示:
/nREQUEST:/n <? xml version="1.0" encoding="UTF-8" ?> < soap:Envelope xmlns:soap ="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd ="http://www.w3.org/2001/XMLSchema" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" > < soap:Body > < ns1:update xmlns:ns1 ="http://server.bfchuan.com/" > < arg0 > 2 </ arg0 > < arg1 > 2 </ arg1 > < arg2 > "bfc" </ arg2 > </ ns1:update > </ soap:Body > </ soap:HelloImpl > /nRESPONSE:/n <? xml version="1.0" encoding="UTF-8" ?> < S:Envelope xmlns:S ="http://schemas.xmlsoap.org/soap/envelope/" >
< S:Body >< ns2:updateResponse xmlns:ns2 ="http://server.bfchuan.com/" >
< return > Fail </ return >
</ ns2:updateResponse >
</ S:Body >
</ S:Envelope >前面是发送的SOAP消息
后面是服务器返回的SOAP消息
如果说你返回的的是个对象,比如查询某个Book,那么返回的服务的SOAP是如下所示:
<? xml version="1.0" encoding="UTF-8" ?>
< S:Envelope xmlns:S ="http://schemas.xmlsoap.org/soap/envelope/" >
< S:Body >
< ns2:byBookResponse xmlns:ns2 ="http://server.bfchuan.com/" >
< return >< desc > BBB </ desc >
< id > 2 </ id >
< name > AAA </ name >
</ return >
</ ns2:byBookResponse >
</ S:Body >
</ S:Envelope >该SOAP返回的是一个对象。
最后题外话:
对于WebService的架构方式,有JAX-WS还有Xfire。对此做个比较:
1) 用基于 jax-ws 的 Client 端调用基于 XFire 和 jax-ws 的 WebService 都没有问题;
而用基于 XFire 的 Client 端调用基于 XFire 的 WebService 存在问题(什么原因目前还不明);
2) 基于 Jax-ws 的 Client 端只能通过解析 WSDL 文档的方式来调用 WebService ,不可以使用将 WebService 的接口抓到本地进行掉用的方式;
基于 XFire 的 Client 端则能够通过两种方式来调用 WebService :(但目前这两种方式只针对 XFire 发布的 WebService )
(1) 将 WebService 的 Interface 抓到本地,进行调用;
(2) 通过得到 WebService 的 WSDLFile 或是 WSDL 的 URL ,解析 WSDL 来调用 WebService ;
3) 基于 jax-ws 的 WebServiceClient 端可以建立在任何 Project 中;
基于 XFire 的 WebServiceClient 端则必须建立在 WebServiceProject 中;
对于非 WebServiceProject 的 Project 要想调用基于 XFire 的 WebService 必须将其 Interface 抓到本地进行调用;
4) 基于 Jax-ws 发布的 WebService 只发布 WSDL 文档,
基于 XFire 的 WebService 则会发布 WSDl+ 服务接口;
5) 基于 Jax-ws 发布的 WebService 会显示的产生 WSDL 文档;
基于 XFire 发布的 WebService 则只是在调用时由服务器产生临时的;
6) Jax-ws 设计了监听器机制, 在WEB.xml中已经能看到监听类的配置了 ; XFire 没有;
分类: 程序员
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于ASP.NET MVC 4 小项目开发总结的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://www.haodehen.cn/did45313