[MVC]ASP.NET MVC Membership 权限 漫谈

mikel阅读(857)

转载:http://www.cnblogs.com/wlb/archive/2009/12/06/1618216.html

以前一位同事习惯于使用Membership来进行权限管理,现在随着ASP.NET MVC的引入,采用以前的方法,提出了以下方案:

ASP.NET MVC+Membership结合,通过在web.config中进行配置,来管理系统中的权限。

于是,我对这个方案的可行性进行了分析,提出了以下疑点:

  1. 在ASP.NET 2.0的Membership中, 在Web.config中是通过物理文件和目录,那么在ASP.NET MVC中,如果在URL中直接输入物理文件和目录,是找不到这个文件的,不知道这种方式还能不能奏效。如果说不管在mvc中,通过URL Routing怎么绕,最终都会定位到物理文件和目录上,这种方式是行得通的。
  2. 如果不是文件目录结构的话,web.config这种配置是否还能用?

关于我提出的这个疑点,当时我觉得非常的有趣。为了验证我的疑点,于是我做了一个测试。

经过一个简单的Demo,测试结果出来了。测试结果如下:

  1.  在ASP.NET MVC的Membership中,并不是基于文件和目录的,而是易于URLRouting的,当进行文件目录配置的话,是不起作用的,只有在web.config中进行URLRouting的权限配置才会起作用。

最终经过测试,如果按照默认路由走的话,最终也是可以通过配置进行权限的控制。只不过是配置起来的话,要把文件路径改为“controller/action”而不是原来的“Controller/Action.aspx”。

 

接下来再想一想,这样会不会有什么问题?

  1.  以 往的Webform开发,url是稳定因素(URL重写除外),所以,通过Membership进行权限设定是没有问题的。但是在MVC中,URL是不稳 定因素,如果更改了routing设置,权限系统就会被绕过去。从模块职责上来说,不应该因为其它模块的更改,导致权限管理模块失效,这从设计上就是一个 糟糕的设计。所以,从个人情感上来说,我认为这种设计糟糕透了。
  2. 既然URL是不稳定因素,不应该通过这个来进行权限控制,也就是说不应该通过不稳定因素来参杂权限管理。
  3. URL 是不稳定的,那么较稳定的因素应该就是Controller跟Action,也就是说,无论URL怎么变,最终都可以把Controller跟 Action确定下来。因此,在ASP.NET MVC中,应该通过Controller跟Action结合来进行权限控制。
  4. 了解URLRouting的朋友们一定知道,MVC中的路由是按照顺序执行的,如果满足了前面的匹配规则,将不会执行后面的匹配规则,稍稍对于URLRouting掌握不好,就会给系统的安全带来隐患。

权限系统一般分为:稳定不变的部分、较稳定的部分、不稳定部分。因此在进行权限系统的时候就应当综合考虑这些因素。

关于权限系统的设计,一般都会按照如下来设计:

  1. 抽象出系统中的实体部分(系统中稳定不变的部分或系统中较稳定的部分)。
  2.  将抽象的实体部分进行抽象设计(实体类)。
  3. 设计实体类之间的存储。
  4. 分析实体类之间的关系,这些是系统中不稳定的部分,因此要将这些关系进行存储(存储在数据库中或配置文件中,方便以后进行修改)。

经过如上的设计,一般来说当权限管理系统达到如下要求就算是合格了:

  1. 能完成基本的权限管理
  2. 当需要进行权限管理的时候,整个权限系统的架构不变,变的仅仅是数据。

一个合格的权限系统的设计通常不够完美,所以需要结合实际情况综合考虑进行改进。至于如何改进,没有统一的方法可言。

关于Membership,很多人都喜欢重用Membership的一些东西,可是究竟能够重用的部分有多少?

  1. ASP.NET 2.0中提供的控件,如: Login、LoginView、PasswordRecovery、CreateUserWizard、ChangePassword等,当然,这些并 不是Membership的部分,但是这些通常都会跟Membership配合使用。这些控件提供了方便的开发,可是通常这些控件并不能满足要求,扩展性 并不好,而且这些控件会生成很多垃圾代码如:js、css等。在带来开发方便的同时,也给扩展跟维护带来不便。最重要的一点,凡是涉及Postback的 控件,在ASP.NET MVC中,全部不能使用。
  2. 数据库及数据库访问。通过执行“aspnet_regSQL”命令,可以自 动在数据库中创建出11张表,并且提供了若干个API方法来对这11张表进行操作。可是这11张表中的设计往往也是不符合要求的,如果进行扩展的话,就会 比较麻烦。一般扩展的方法有两种:不改变原来的表,但是要建一张表跟以前的表对应,表中的Id跟原来表中一模一样;改变原来表的设计。无论是哪种方法,数 据库访问部分就必须得重写,因此数据库及数据库访问的重用也变的非常低。
  3. 基于配置文件的权限控制,似乎从目前上来看,能重用的部分只有这个了。可是在ASP.NET MVC中URL是个不稳定因素,基于配置文件的权限控制这个功能的重用并不适合ASP.NET MVC的开发。

综合对比一下,至少在ASP.NET MVC开发中,Membership所带来的重用微乎其微。

 

在 不同的权限管理系统中,对控制级别的要求是不一样的,如:页面访问级别、数据访问级别、控件访问级别、函数级别。。。。。。可是不论是要控制到那个级别, 权限管理系统所要完成的功能都是一样的 。我们不妨给权限管理系统下一个定义:权限管理系统就是告诉其它模块用户/角色对特定的资源/功能是否具有访问的权限。

在Webform中,用户跟角色相比,角色是不稳定因素,用户是相对较稳定的因素。因此权限系统的输入参数中我们通常会传入用户,而不输入角色,因为角色是不稳定的,至于说用户属于哪个角色,权限系统是可以查出来的。

而在ASP.NET MVC中,用户跟角色都可以是较稳定因素,因为用户的权限控制跟角色的权限控制都是通过扩展标记属性来实现的。这是跟webform相比,权限系统设计上不一样的地方。

 

ASP.NET MVC中权限控制是通过对Action的拦截实现的。实现的方式如下:

  1. 定义一个扩展属性标记类,继承自接口IActionFilter的抽象类ActionFilterAttribute。
  2. 重写ActionFilterAttribute中的虚方法。
  3. 将扩展标记作用于Controller跟Action。

关于ASP.NET MVC中的权限管理方案,网上已经有了,这里就不过多的赘述了。

 

以下是我前段时间设计的权限管理系统的类关系图,只完成了部分的设计,还有个别部分没有加上, 是使用PowerDesigner 15设计的,由于这段时间非常的忙,没有继续完成剩下的功能。如果以后有时间,我会完成剩下的设计,然后重新上传。

权限管理系统类关系图 

 

作者:深山老林
出处:http://wlb.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

[JQuery] jQuery Validation插件remote验证方式的Bug

mikel阅读(860)

转载:http://www.cnblogs.com/JeffreyZhao/archive/2009/12/04/jquery-validate-remote-bug.html

评论依然精彩,希望感兴趣的去原址看评论

JQuery插件很多,其中一个重要的插件便是jQuery Validation, 它的作用是对表单进行验证,还上了JQuery官网。不过奇怪的是,最近用下来感觉有些古怪,因为好像有些死板,已有功能的应变能力还不强,甚至还有个奇 怪的Bug。任何项目有Bug其实也正常,但这个Bug其实是一个文档上已经记载了,却没有实现的功能,这就有些说不过去了。这个问题便出在remote 验证方式上,还好修改起来非常容易,在此记录一下,也方便以后的参考。

在表单验证时,有时候会需要发一个AJAX请求去服务器上进行判断,例如在用户注册时检查用户名是否存在。jQuery Validation插件提供了一种remote方式来实现这一点。例如我可以这样验证表单:

<form id="regForm">
<input type="text" name="userName" />
</form>
<script language="javascript">
$('#regForm').validate({
'rules': {
'userName': {
'required': true,
'remote': '/account/verify'
}});
</script>

这样,jQuery Validation便会请求“/account/verify?userName=jeffz”这样的URL来获取true/false。可惜的是,我 们在使用ASP.NET MVC时,往往会将input的name写为特定的形式,目的是利用DefaultModelBinder的强大绑定功能。例如:

<form id="regForm">
<input type="text" id="userName" name="user.Name" />
</form>

与此同时,我们用来进行验证的Action方法,它的参数名可能也有所不同:

public ActionResult Verify(string name) { ... }

根据文档描述,此时我们应该这样写:

$('#regForm').validate({
'rules': {
'user.Name': {
'remote': {
url: '/account/verify',
data: {
name: function() { return $("#userName").val(); }
}}}}});

可是,从实际效果来看,jQuery还是在请求“/account/verify?user.Name=jeffz”,百思不得其解。确认在三之后只得求助于jquery.validation.js源码,看后差点晕过去:

remote: function(value, element, param) {
if ( this.optional(element) )
return "dependency-mismatch";
...
param = typeof param == "string" && {url:param} || param;
if ( previous.old !== value ) {
previous.old = value;
var validator = this;
this.startRequest(element);
var data = {};
data[element.name] = value; // data还是以element.name为准?
$.ajax($.extend(true, {
url: param,
mode: "abort",
port: "validate" + element.name,
dataType: "json",
data: data,
success: function(response) {
...

我很奇怪,不知道为什么会这样做,这样根本没有起到指定参数名的作用。那么,改吧:

remote: function(value, element, param) {
if (this.optional(element))
return "dependency-mismatch";
...
param = typeof  param == "string" && {url:param} || param;
if (previous.old !== value) {
previous.old = value;
var validator = this;
this.startRequest(element);
var data = {};
data[element.name] = value;
$.ajax($.extend(true, {
// url: param,
url: param.url,
mode: "abort",
port: "validate" + element.name,
dataType: "json",
// data: data,
data: param.data || data,
success: function(response) {
...

修改两处即可,问题就此解决。只可惜,jquery.validate.min.js类似的文件只能自己进行压缩了。

居然会出现这样的问题,实在令人费解。

[C#]NeatUpload——支持大文件上传的控件

mikel阅读(1230)

转载:http://www.cnblogs.com/dreamof/archive/2009/12/03/1616371.html 

 在【推荐】.NET批量上传控件——HtmlInputFiles 一文中有博友向我推荐了NeatUpload上传控件,于是花了点时间对该控件进行了简单的学习,感觉这个控件真的不错,不但能够支持大文件上传,而且还有上传进度条,更重要的是NeatUpload控件是为数不多的支持大文件上传的免费控件,废话不说了,下面先介绍NeatUpload控件如何使用。
  NeatUpload控件下载

  一、前期准备

  1、下载neatupload的免费版本http://www.brettle.com/neatupload#Download 

  2、访问地址http://www.brettle.com/Demo.aspx查看相应的Demo示例; 

  3、将Brettle.Web.NeatUpload.dll添加到工具箱; 

  4、将\NeatUpload-1.2.32下的NeatUpoad文件夹复制到项目根目录; 

  5、在Web.configsystem.web节点中写入下面的配置 

  <httpModules>

        <add name="UploadHttpModule" type="Brettle.Web.NeatUpload.UploadHttpModule, Brettle.Web.NeatUpload" />

  </httpModules> 

  <httpRuntime maxRequestLength="400000" executionTimeout="3600" /> 

  二、NeatUpload.net中的运用

  前台代码

    <Upload:ProgressBar ID="ProgressBar1" runat="server" Inline="True"

        Triggers="" />

       <br />

    <Upload:InputFile ID="AttachFile" runat="server" />

    <br />

    <br />

<asp:Button ID="BtnUP" runat="server" onclick="BtnUP_Click" Text="上 传" />

 

后台代码

        protected void BtnUP_Click(object sender, EventArgs e)

        {

            if (AttachFile.HasFile)

            {

                string FileName = this.AttachFile.FileName;//获取上传文件的文件名,包括后缀

                string ExtenName = System.IO.Path.GetExtension(FileName);//获取扩展名

                string SaveFileName = System.IO.Path.Combine(System.Web.HttpContext.Current.Request.MapPath("UpLoads/"), DateTime.Now.ToString("yyyyMMddhhmm") + ExtenName);//合并两个路径为上传到服务器上的全路径

                AttachFile.MoveTo(SaveFileName, Brettle.Web.NeatUpload.MoveToOptions.Overwrite);

                string url = "UpLoads/" + DateTime.Now.ToString("yyyyMMddhhmmss") + ExtenName; //文件保存的路径

                float FileSize = (float)System.Math.Round((float)AttachFile.ContentLength / 1024000, 1); //获取文件大小并保留小数点后一位,单位是M

            }

    }

附图如下
    

[SQL]使用CLR存储过程方便快捷导出数据到Excel

mikel阅读(1040)

转载:http://www.cnblogs.com/NickYao/archive/2009/12/03/1616101.html

  今天早上看到一篇文章(Exporting to Excel Using a CLR Stored Procedure )觉得非常实用,就拿来跟大家分享一下。  
  这篇文章主要提供了一个SQL Server导出数据到Excel一个快捷方便的方式,如果你日常工作常常需要从数据库导出数据到Excel的话,你会发现这对你非常有用。
    

  好了,废话少说,我这里就简单说一下如何使用:
     1. 下载代码ExcelExport.zip
     2. 编译项目,把生成的dll复制到一个目录,例如:c:\CLR
     3. 在SQL SERVER上启用CLR

sp_configure'clr',1
reconfigure

  4. 使用Alter DATABASE 命令打开 Trustworthy 数据库属性

Alter DATABASE 数据库名 SET TRUSTWORTHY ON

  5. 创建程序集

Create ASSEMBLY ExportToExcel
FROM 
'C:\CLR\ExcelExport.dll' CLR 程序集存放的地方
WITH PERMISSION_SET 
= EXTERNAL_ACCESS

  6. 创建一个存储过程关联到上一步创建的程序集

Create PROCEDURE[dbo].[prc_ExportToExcel]
       @proc [nvarchar](100),
       @path [nvarchar](200),
       @filename [nvarchar](100),
       @params xml
AS
EXTERNAL NAME [ExportToExcel].[StoredProcedures].[ExportToExcel]

  7. 好了,到这里准备工作就算完成了,下面是使用的例子:

Declare @params xml
Set @params 
= '<params><param name="lastname" value="Smith" /><param name="country" value="US" /></params>'
exec prc_ExportToExcel 
'procname',‘Drive:\Directory\''Filename', @params

  a) 第一个参数是获取数据的存储过程名

  b) 第二个参数是输出的目录

  c) 第三个参数是输出的文件名,不需要带后缀

  d) 第四个参数是获取数据的存储过程需要的参数。name代表参数名,value代表参数值。

    如果获取数据的存储过程没有参数的话,就使用:Set @params ='<params></params>'

[ASP.NET].NET批量上传控件——HtmlInputFiles

mikel阅读(828)

转载:http://www.cnblogs.com/dreamof/archive/2009/12/02/1615515.html

  此控件支持多个文件同时上传,而且上传文件的数量、大小及格式可以根据自己的需要进行设置,并且使用非常简单。
  HtmlInputFiles控件下载

  1HtmlInputFiles控件属性

  下图是该控件的主要属性:
  

  属性名              功能

  FileFilter             设置上传文件的类型

  MaxCount               设置最多可以上传几个文件

  RecordCount            设置上传控件的初始值

  FileSize               设置上传文件的大小

  其它属性的功能一目了然,就不介绍了。

  2HtmlInputFiles控件运用

  下图为该控件使用中的截图
   
  

  “添加上传”按钮用来增加上传附件,“减少上传”按钮用来减少上传附件。

  具体使用如下:

  前台代码:

    <div>   

        <cc1:HtmlInputFiles ID="HtmlInputFiles1" runat="server" AddButtonVisible="True" MaxCount="15" RecordCount="1" FileFilter=".GIF|.JPG|.JPEG|.RAR|.TXT" />   

        <br />

        <asp:Button ID="BtnUpfile" runat="server" onclick="BtnUpfile_Click" Text="上 传" />

    </div>
  后台代码:

        protected void BtnUpfile_Click(object sender, EventArgs e)
        {

            if (this.HtmlInputFiles1.CheckAllPostedFile(true))

            {

                for (int i = 0; i <= this.HtmlInputFiles1.RecordCount; i++)

                {

                    System.IO.FileInfo info = new FileInfo(this.HtmlInputFiles1[i].PostedFile.FileName);

                    string fileName = info.Name;

                    string filePath = "UpLoads/" + System.Guid.NewGuid().ToString() + fileName;                   

                    this.HtmlInputFiles1[i].PostedFile.SaveAs(Server.MapPath(filePath));

                }

            }

        }

[HTML]你真的知道一个HTML及资源是如何load的吗?

mikel阅读(875)

转载:http://www.cnblogs.com/mindsbook/archive/2009/12/03/sequence_of_response.html

作者:朱涛

出处http://www.cnblogs.com/mindsbook/archive/2009/12/03/sequence_of_response.html

摘要

本文主要介绍浏览器请求一个URI后, 相应的html及其包含的外部资源(如js/css/image/flash)的下载顺序及其执行顺序.

在文中会有一个具体的例子来说明.

引入

完成了若干个基于WEB的项目, 也了解了从前端的js,css,html到后端python/php等, 二者如何交互, 最终浏览器如何执行, 这些在心里也已经很明确了. 不过一个问题一直萦绕在心中,那就是:

一个html有若干个外部资源(js,css,flash,image等),这些请求是何时下载的,又是何时执行的?

不清楚,不明白, 所以也就不知道我写的js究竟何时执行的, 也就不知道为什么很多高性能的建议是要将js置于一个 html底端的</body>之前.

如果你也不是很明确,请来和我一起学习吧.

具体分析

首先我们来看一个示例的html页面,如下:

<html>
<head>
<script src="/static/jquery.js" type="text/javascript"></script>
<script src="/static/abc.js" type="text/javascript">
</script>
<link rel="stylesheets" type="text/css" href="/static/abc.css"></link>
<script>
$(document).ready(function(){
$("#img").attr("src", "/static/kkk.png");
});
</script>
</head>
<body>
<div>
<img id="img" src="/static/abc.jpg" style="width:400px;height:300px;"/>
<script src="/static/kkk.js" type="text/javascript"></script>
</body>
</html>

它有如下几种资源:

  1. 3个外部js文件,1个inline js代码
  2. 1个外部css文件, 1个inline css代码
  3. 1个image文件,及1个js请求的image

总共是6个http request.

在分析之前,我们来看看firefox对这个html请求的结果, 如下图:

http://i48.tinypic.com/21n0hw7.jpg

我们再看看chrome(linux)对这个html的请求结果,如下图(图比较小,可以在新标签中打开):

http://i48.tinypic.com/wck1ue.jpg

我们先分析下,然后再去说明这2种请求结果的不同.

请求分析

首先说明下面这些描述主要是基于自己google, 咨询朋友和在 SO 和 IRC 上获得, 我并没有阅读相关的spec(当然我很想阅读,如果知道相关spec的朋友请留言谢谢), 不能保证其正确性和准确性,风险自担 :D.

基于相关的调研, 我的理解为, 对于一个URI请求, 浏览器会按照下面的请求和执行顺序进行:

  1. 一个线程对DOM进行下载(也就是html, 而不去管html中的外部资源)
  2. 另外一个线程会开始分析已经下载的DOM, 并开始下载其中的外部资源(如js, css, image等)
  3. 第三个线程(如果有的话)会去下载2正在下载的以外的外部资源
  4. 如果允许更多的连接, 更多的线程会继续下载其它资源

一个请求可以同时有多少个connection(线程), 取决于不同的浏览器, http1.1 标准中规定的是对于同一个server/proxy(也就是hostname) 不超过2个connection, 但是在实际的浏览器实现中, 具体如下:

Firefox 2: 2
Firefox 3: 6
Opera 9.26: 4
Opera 9.5 beta: 4
Safari 3.0.4 Mac/Windows: 4
IE 7: 2
IE 8: 6

所以请根据这个实际情况来思考上面的下载顺序.

然后我们看执行顺序(js的执行, css的应用等):

  1. 只要浏览器"看到了"了js代码,它就会执行
  2. 浏览器是从下到下,一行一行地执行
  3. 如果js代码位于一个函数或者对象中,则只有当函数或者对象被调用时才会执行
  4. 而所谓的direct code(不处于函数或者对象中的代码),则会从上到下顺序执行
  5. 当css文件下载完成时, 相应的样式也会应用到DOM上
  6. onload或者JQuery的$(document).ready()是在DOM下载完成后执行

在实际的浏览器中, 一般遇到<script>标签会自动block住其它线程的下载, 如firefox, 这也是为什么 在web开发中常常推荐将<script>标签置于</body>之前的原因.

但是并非所有的浏览器都block, 如chrome并不会block住其它的connection. 所以具体的load还需要参考具体的浏览器实现.

建议, 将<script></script>标签置于</body>之前, 这样可以在大多数情况下都得到较好的性能.

对Firefox和chrome的请求分析

我们回过头来看下上面2个图中的请求响应图.

Firefox

有如下特征:

  1. 首先下载html
  2. html下载完成后, 从上到下依次下载外部文件(js, css,img)
  3. js会block其它外部文件的下载
  4. 其它文件会并行下载

chrome

有如下特征:

  1. 首先下载html
  2. 从上到下依次下载外部文件(js,css,img)
  3. 各个资源的下载顺序是并行的

你可能会奇怪如果js可以并行下载,那么可能位于DOM下面的代码会先执行, 首先可以肯定的是 即使下面的js先完成下载,也不会影响到整体的从上到下的执行顺序,浏览器会维护这种顺序的关系, chrome的这种方式也是未来浏览器的一种趋势, 而这也是为什么chrome能够更快的原因之一.

有意思的一个插曲

在提出这个问题后,我便多方入手, 向朋友咨询, 向 SO 提出问题, 甚至去Firefox的 IRC 进行了提问,

回答的朋友还都是很耐心的, 不过, 他们大多向我问了一个问题 做WEB开发, 你为什么要了解这些细节.

对于这样的问题,我还是比较纳闷的, 我一直认为 一个好的程序员,不仅需要知道how, 还要知道what, 甚至why,

知道how,只说明你是一个合格的码工,只会简单地使用别人提供的东西来开发.

知道what, 说明你开始去关注背后是如何实现的, 随着时间推进, 这时候你会逐渐成为一个有经验的程序员.

知道why, 说明你开始向hacker的路迈进了, 开始逐步走向了技术牛人的路线了,长此以往你会有很大的成长的. 参考 How To Become A Hacker.

让我们去享受细节,本质的快乐吧,而不是只停留在我会的层面那么表面的快乐.

结论

浏 览器是各大厂商抢占的市场,无论是自主(Firefox, chrome, IE, Opera, Safari)或者基于一定的内核(遨游, 搜狗, TT, 360等), 但是可以肯定的是浏览器会更加强大, 遵守规范, 更快的响应等, 而我们WEB程序员的日子也会好过很多.

本文部分细节还是比较含糊, 后面可能还会在写一篇文章来进行更彻底,清晰的说明.

欢迎讨论.

后记

这次是不惜血本了, 之前积累了快400的 SO reputation score, 一下压出去了150个来寻找最满意的答案.

具体大家可以参考:

Load and execution sequence of a web page?

帖子中有较详细的回答,可以作为参考.

本文的源码

本文的rst源码链接在 这里 .

点击 下载pdf阅读 (如果浏览器不支持直接打开,请点击右键另存)

[JQuery]Jquery快速构建可拖曳的购物车-DragDrop

mikel阅读(846)

拖曳功能早已经成为各个网站吸引用户的一大亮点,那有没有想过如何把拖曳功能应用到电子商务网站的购物车功能模块中呢? 这样一来,购买者只需要把自己感兴趣的商品拖曳到自己的购物车中,也可以从购物车中删除商品 同时更新购物车的总体价格和数量。

那咱们就开始实例吧,本实例并没有链接数据库读取数据来初始化Products,而是创建了一些虚拟的商品如下:

 

1、  创建Product实体类

 

public class Product

    {

        public string Code { get; set;  }

        public string Name { get; set; }

        public string Description { get; set; }

        public double Price { get; set; }

}

 

2、  构建商品List<Product>

 

public class Product

    {

        public string Code { get; set;  }

        public string Name { get; set; }

        public string Description { get; set; }

        public double Price { get; set; }

}

 

3、创建DataList并绑定List<Product>

 

<asp:DataList ID="dlProducts" RepeatColumns="3"

         RepeatDirection="Horizontal" runat="server">

 

    <ItemTemplate>

 

    <div class="productItemStyle" price='<%# Eval("Price") %>'

         code='<%# Eval("Code") %>'  id='item_<%# Container.ItemIndex + 1 %>'>

    <li>

    <%# Eval("Code") %>

    </li>

    <li>

    <%# Eval("Name") %>

    </li>

    <li>

    <%# Eval("Description") %>

    </li>

 

     <li>

    $<%# Eval("Price") %>

    </li>

    </div>

 

    </ItemTemplate>

 

    </asp:DataList>

 

private void BindData()

{

    var products = GetProducts();

 

    dlProducts.DataSource = products;

    dlProducts.DataBind();

}

 

productItemStyle 样式名称

Container.ItemIndex动态生成连续的商品编号

 

4、  生成Products Div Draggable

下载最新的JQuery JS文件及其UI文件:

<script language="JavaScript" type="text/JavaScript" src="JQuery-1.2.6.min.js"></script>

<script language="JavaScript" type="text/javascript"

src="JQuery-ui-personalized-1.6rc4.min.js"></script>

 

页面初始化时生成Div Draggable

 

$(document).ready(function() {

 

        $(".productItemStyle").draggable({ helper: "clone", opacity: "0.5" });

)};

 

5、创建一个DropZone

 

DropZones 是购物车区域

 

$(".dropZone").droppable(

        {

            accept: ".productItemStyle",

            hoverClass: "dropHover",

            drop: function(ev, ui) {

 

                var droppedItem = ui.draggable.clone().addClass("droppedItemStyle");

 

                var productCode = droppedItem[0].attributes["code"].nodeValue;

                var productPrice =

                 getFormattedPrice(droppedItem[0].attributes["price"].nodeValue);

 

                var removeLink = document.createElement("a");

                removeLink.innerHTML = "Remove";

                removeLink.className = "deleteLink";

                removeLink.href = "#";

                removeLink.onclick = function()

                {

                    $(".dropZone").children().remove("#" + droppedItem[0].id);

                    updateTotal(productPrice * (-1));

                }

 

                droppedItem[0].appendChild(removeLink);

 

                $(this).append(droppedItem);

 

                updateTotal(productPrice);

            }

        }

        );

 

Accept参数:展示Class= productItemStyleDiv

hoverClass参数:当有Product放到DropZone时的样式

drop函数:当Product拖放到DropZone时出发的函数,此函数主要做了一个Product ItemClone,价格的计算、添加Remove按钮以及到点击Remove按钮时所触发的事件。

 

价格的计算updateTotal()函数

// update the total!

    function updateTotal(price) {

 

        total += parseFloat(price);

        $("#total").html(total.toFixed(2));

        $(".shoppingCartTotal").effect("bounce");

 

}

 

最终效果如下图:

 

 

 

英文原文地址:http://www.codeproject.com/KB/aspnet/JQueryShoppingCart.aspx

 

 

版权

作者:灵动生活

出处:http://www.cnblogs.com/ywqu

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

 

[图书]SEO Warrior

mikel阅读(759)

书名:SEO Warrior

ebook

作者:Jerkovic John
出版:O’Reilly Media 2009
ISBN:059615707X
格式:PDF;7.3MB;494页

下载链接/download link:
rapidshare

[MVC]ASP.NET MVC实践系列11-FCKEditor和CKEditor的使用

mikel阅读(843)

转载:http://www.cnblogs.com/nuaalfm/archive/2009/11/27/1612027.html

FCKEditor是一款强大的在线编辑器,简单实用,多浏览器兼容,免费开源,应用十分广泛,据他的官方网站上称有三百多万的下载量,而且无数的 知名大公司正在使用它。所以FCKEditor是很值得信赖的,现在 FCKeditor项目已转向下一代版本命名CKEditor的产品开发,基本上采用Fckeditor并对部分进行了重新设计和采用新技术以改善结构, 性能更好扩展性更强。下面我们来介绍一个这两个编辑器,对于FCKEditor我们只讲一下在ASP.NET MVC中的用法其配置可以参考官方文档。

一、FCKEditor使用:

1、FCKEditor在ASP.NET MVC中的应用:

首先到http://ckeditor.com/download下载FCKeditor 2.6.5(我下载的时候报地址暂时有问题,但FCKEditor网上保有量很多,可以任意下载一个),将下载好的文件解压缩然后拷贝到你项目的Content文件夹下:

View

 

View代码

Controller:

 

Controller

 1 [AcceptVerbs(HttpVerbs.Post)]
 2         [ValidateInput(false)]
 3         public ActionResult Test(string FckEditor1)
 4         {
 5             this.ValidateRequest = false;
 6             return Content(FckEditor1);
 7         }
 8         public ActionResult Test()
 9         {
10             return View();
11         }

 

 这里要注意[ValidateInput(false)]特性,它的目的是为了防止在提交时报“检测到有潜在危险的客户端输入值”,另外这里还有 个奇怪的现象就是这个View不能在Index.aspx中,在Index.aspx即使使用了[ValidateInput(false)]特性还是会 报错,换个新View就没这个问题了,不知道为什么?

2、Helper版

为了让大家使用的更简单,我写了个Helper版,大家参考下:

 

Helper

View:

 

代码

<script src="<%= Url.Content("~/Content/fckeditor/fckeditor.js") %>" type="text/javascript"></script>
     
<%=Html.FckEditor(Url.Content("~/Content/fckeditor/"), "lfm"new { x = "x" })%>

 

二、CKEditor使用

1、CKEditor在ASP.NET MVC中的应用:

首先到http://ckeditor.com/download下载CKEditor。

CKEditor在ASP.NET MVC的使用就相当的简单了,只需要在脚本中执行CKEDITOR.replace(id);id为你需要拥有编辑功能的textarea的id。

View:

 

代码

     <script src="<%= Url.Content("~/Content/ckeditor/ckeditor.js") %>" type="text/javascript"></script>
    
<% using (Html.BeginForm())
       { 
%>
    
<%= Html.TextArea("ckEditor1""Some Value",   new { @name="ckEditor1" })%>
    
<input type="submit" value="提交" />
    <% } %>
    
<p>
    
</p>

        
<script type="text/javascript">
            CKEDITOR.replace(
'ckEditor1');
     
</script>

结果:

 

2、CKEditor配置:

CKEditor配置也很容易, 使用CKEDITOR.replace方法,根据不同的参数来应用不同的配置,例如

 

代码

<script type="text/javascript">
     CKEDITOR.replace( 
'editor2',
      {
       extraPlugins : 
'uicolor',
       uiColor: 
'#14B8C4',
       toolbar :
       [
        [ 
'Bold''Italic''''NumberedList''BulletedList''''Link''Unlink' ],
        [ 
'UIColor' ]
       ]
      } );
    
</script>

得到的结果:

其他配置可以参考官方文档。同时_samples文件夹中也有大量例子可供参考。

3、CKEditor瘦身:

如果你觉得整个编辑器太大,你可以删除文件。

例如把_samples、_source、文件夹删除,进入lang文件目录,保留en.js、zh.js、zh-cn.js三个文件,其余的语言文件如果你用不到,可以删除。

三、参考

http://www.ff-bb.cn/logs/46479725.html

http://www.codeproject.com/KB/aspnet/fckeditor.aspx

 

我的ASP.NET MVC实践系列

ASP.NET MVC实践系列1-UrlRouting

ASP.NET MVC实践系列2-简单应用

ASP.NET MVC实践系列3-服务器端数据验证

ASP.NET MVC实践系列4-Ajax应用

ASP.NET MVC实践系列5-结合JQuery

ASP.NET MVC实践系列6-Grid实现(上)

ASP.NET MVC实践系列7-Grid实现(下-利用Contrib实现)

ASP.NET MVC实践系列8-对查询后分页处理的解决方案

ASP.NET MVC实践系列9-filter原理与实践

ASP.NET MVC实践系列10-单元测试

其他:

在ASP.NET MVC中对表进行通用的增删改