好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

ASP.NET MVC 4 小项目开发总结

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 小项目开发总结的详细内容...

  阅读:48次