[原创]ASP.NET MVC使用EasyUI的datagrid多选提交保存教程

mikel阅读(1268)

需要实现EasyUI的datagrid组件加入选择checkbox列,并提交后台批量添加的功能,页面代码如下:

<script language="javascript" type="text/javascript">
    $(function() {
        //searchbox
        $('#selectgoods-keywords').searchbox({
            searcher: function(val, name) {
                searchInfo(val);
            }
        });
        //datagrid
        $('#selectgoods-grid').datagrid({
            url: '/Goods/List',
            pageNumber: 1,
            pageSize: 20,
            pageList: [20, 40, 60, 80, 100]
        });
        //form



    });
    
    function searchInfo(val){
        //            var keytype=$('#keyType').combobox('getValue');
            var keytype = 'Goods_Name';
            var keywords = val;
            $('#selectgoods-grid').datagrid('reload', { keytype: keytype, keywords: keywords });
    }

    function saveSelectGoods() {
        var ids = [];
        var rows = $('#selectgoods-grid').datagrid('getSelections');
        for (var i = 0; i < rows.length; i++) {
            ids.push(rows&#91;i&#93;.Identifier);
        }
        var selectsupplier = '<%=ViewData&#91;"supplier"&#93; %>';
        $.post('/SupplierGoods/SaveSelect', { supplier: selectsupplier, checks: ids.join(',') }, function(data) {
            if (data) {
                $('#goodslist-grid').datagrid('reload');
                $('#goodsInfo-window').window('close');
            } else {
                alert('保存失败!');
            }

        }, 'json');
    
    }
        
</script>
    <div style="width:100%; height:100%">
			                 <table id="selectgoods-grid" class="easyui-datagrid" fit="true" toolbar="#tlb_selectgoods_search" pagination="true" 
			rownumbers="true" fitColumns="true"  idField="Identifier">
		                <thead>
                <tr>
                <th field="ck" checkbox="true"></th>  	    			   
            <th field="Identifier" hidden="true" width="0" editor="text">Id</th>
            <th field="Goods_Name" width="100" editor="{type:'validatebox',options:{required:true}}">商品名称</th>
            <th field="Chemistry" width="100" editor="{type:'validatebox',options:{required:true}}">化学指标</th>
            <th field="Physical" width="100" editor="{type:'validatebox',options:{required:true}}">物理指标</th>
            <th field="Partner_Name" width="50" editor="{type:'validatebox',options:{required:true}}">合作状态</th>
              </tr>			
		                    </thead>
	                    </table>
              
	<div id="tlb_selectgoods_search">
商品名称:<input name="keywords" id="selectgoods-keywords" class="easyui-searchbox" /><a href="#" class="easyui-linkbutton" iconCls="icon-save" plain="true" onclick="javascript:saveSelectGoods()">保存</a>

	</div>    
    </div>

ASP.NET MVC的Controller代码如下:

        /// <summary>
        /// 多选商品添加
        /// </summary>
        /// <param name="supplier">供货商ID</param>
        /// <returns></returns>
        public ActionResult SelectGoods(string supplier)
        {
            ViewData["supplier"] = supplier;

            return View();            
        }
        /// <summary>
        /// 保存批量添加的产品信息
        /// </summary>
        /// <param name="checks">选中的商品ID</param>
        /// <param name="supplier">供货商名称</param>
        /// <returns></returns>
        public JsonResult SaveSelect(string checks, string supplier)
        {
            JsonResult result = new JsonResult();
            result.Data = false;

            try
            {

                if (String.IsNullOrEmpty(supplier))
                    return result;

                SupplierGoods goods = new SupplierGoods();
                goods.Identifier = 0;
                //拼装xml
                String ids=Communion.StringHelper.BuildXmlID(checks);
                goods.Goods_ID = -1;//标示批量插入
                goods.Note = ids;
                goods.Month_Output = Convert.ToDouble(String.IsNullOrEmpty(this.ReadFromRequest("Month_Output")) ? "0" : this.ReadFromRequest("Month_Output"));
                goods.Supplier_ID = Convert.ToInt32(supplier);
                goods.Create_Date = DateTime.Now;
                goods.Customers = this.ReadFromRequest("Customers");
                goods.Equipment = this.ReadFromRequest("Equipment");
                goods.Detail_Params = this.ReadFromRequest("Detail_Params");
                goods.IsDefault = Convert.ToInt32(String.IsNullOrEmpty(this.ReadFromRequest("IsDefault")) ? "0" : this.ReadFromRequest("IsDefault"));
                Business business = new BusinessLogic();
                int id = business.Save<SupplierGoods>(goods);
                if (goods.Identifier == 0)
                {
                    goods.Identifier = id;
                }
                result.Data = true;
                return result;

            }
            catch (Exception e)
            {
                return result;
            }            
        }

存储过程利用xml变量对传入的xml类型的ID集合进行批量添加保存到数据库中,存储过程代码如下:

ALTER PROCEDURE [dbo].[View_SupplierGoodsCreate]
	@Identifier int,
	@Supplier_ID int,
	@Goods_ID int,
	@isDefault int,
	@Create_Date datetime,
	@Month_Output float(8),
	@Goods_Name nvarchar(400)=NULL,
	@Physical nvarchar(400)=NULL,
	@Chemistry nvarchar(400)=NULL,
	@Customers nvarchar(400)=NULL,
	@Equipment nvarchar(400)=NULL,
	@Note nvarchar(MAX)=NULL,
	@Detail_Params nvarchar(400)=NULL
AS
IF @Goods_ID=-1
BEGIN
		--批量插入商品
		DECLARE @xml xml
		SET @xml=@Note
		INSERT INTO Supplier_Goods(Supplier_ID,Goods_ID,Create_Date,Month_Output,Customers,Equipment,Note,isdefault,Detail_Params)
		SELECT @Supplier_ID,identifier,@Create_Date,0,null,null,null,0,null 
		FROM Base_Goods		
		WHERE
			 Identifier in (Select 
			T.ID.value('.', 'int') As ID
		From
			@xml.nodes('/XML/ID') as T(ID)) and Identifier not in (select goods_id from Supplier_Goods where Supplier_ID=@Supplier_ID)
		SET @Identifier=@Goods_ID	
END

[转载]数据自动备份解决方案

mikel阅读(1067)

[转载]数据自动备份解决方案 – Andrew.Wangxu – 博客园.

1:网盘自动备份(隔离备份)

隔离备份介绍:直接在网盘内建立项目、文件进行稿写操作很可能会与网盘数据不同步导致数据丢失完整性,对文件造成损坏,所以这种方式是不可取的。因此采用隔离备份,所谓隔离备份就是在A文件夹进行稿写,当关闭计算机时自动备份A文件夹的所有内容到 B文件夹(这里B文件夹是网盘目录)

进行隔离后,稿写与备份互不干扰,双份数据。达成目的流程如下:

1.开机时候网盘程序运行,自动备份网盘文件夹内的内容

2.关机时拷贝当前正在稿写的文件夹内容到网盘文件夹

数据测试截图:

左侧是网盘 右侧是本机,这是关机时自动进行的数据备份。

网盘生成文件夹截图

—————————————————–

实现过程如下:

建立一个批处理程序代码如下:

@echo off  
set "mydate=%date:~0,4%年%date:~5,2%月%date:~8,2%日"  
if exist "d:\金山快盘\%mydate%*" (  
   echo 已经备份过了  
   exit  
) else (  
   goto :back  
)  
  
  
  
  
:back  
net stop mssqlserver  
set "now=%date:~0,4%年%date:~5,2%月%date:~8,2%日%time:~0,8%"  
set "now=%now::=%"  
set "now=%now: =%"  
md "d:\金山快盘\%now%"  
xcopy D:\公司项目\*.* D:\金山快盘\%now% /e /h  
echo md "d:\金山快盘\%now%"  
pause

(注:这里我为了包含SQL的数据库一起备份,所以我先停止了SQL服务再进行的备份,否则是无法拷贝SQL数据库文件的)

写好批处理后如何让这个批处理关机运行呢?

如下操作即可:

1:开始 — 运行 — 输入gpedit.msc 然后出来了组策略.计算机配置—windows设置—脚本(启动和关机)  双击关机策略,再点添加–浏览到你的批处理文件.

就可以了。

如图:

大功告成。

[翻译]ASP.NET MVC 3 开发的20个秘诀(二)[20 Recipes for Programming MVC 3]:自动生成控制器和视图

mikel阅读(937)

[翻译]ASP.NET MVC 3 开发的20个秘诀(二)[20 Recipes for Programming MVC 3]:自动生成控制器和视图 – O2DS – 博客园.

议题

通过您的网站管理动态内容。

解决方案

使用实体框架与数据库绑定,通过Controller以及自动生成的多个视图界面,允许用户创建、读取、更新以及删除(也称为:CRUD)数据。

讨论

在定义控制器和视图之前,需要预先创建模型和DbContext以及数据收集规则(代码优先方法)。在接下来的例子中,将会创建两个类,并实现一个 图书列表管理的功能。第一个类包含书籍信息在SQL Express数据库中存储的数据定义。第二个类将是一个包含Book类型的DbSet对象的DbContext类。创建模型,右键单击Models文件 夹,并选择添加 -> 。在类的文件名写:Book.cs,用下面的代码替换生成的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity; 

namespace MvcApplication4.Models
{
    public class Book
    {
        public int ID { get; set; }
        public string Title { get; set; }
        public string Isbn { get; set; }
        public string Summary { get; set; }
        public string Author { get; set; }
        public string Thumbnail { get; set; }
        public double Price { get; set; }
        public DateTime Published { get; set; }
    } 

    public class BookDBContext : DbContext
    {
        public DbSet<Book> Books { get; set; }
    }

}

*译者注:保存Book.cs后,必须编译整个项目(快捷键Ctrl+Shift+B)才能继续下面的操作。

创建Book的模型和BookDBContext类,接下来就可以开始完成控制器和视图了。开始,右键单击Controller文件夹,选择“添加控制器”(如图 1-1)。

图例 1-1,创建新的控制器

如图所示,将新建控制器命名为BooksControllers。在模板选项卡中选择“包含读/写操作和视图的控制器(使用 Entity Framework)”。模型类选择Book类,数据上下文类选择之前创建的BookDBContext类。视图选项中的Razor(CSHTML)是默 认选项,所以保持不变。内容输入完毕以后点击“新增”,创建文件。(如图1-2)

图例 1-2,新建文件

Entity Framework可以根据已存在的数据库为控制器创建不同的操作方法和视图。在大型项目中,这些基础内容是分开制作的。比如,一个好的前端Web开发人员可能并不是数据库设计方面的专家。因此,数据库设计需要有专业人员负责。

在接下来的例子中,将会连接先前创建的数据库,并为“Book“表创建相应的实例模型。选择使用旧的应用程序还是创建新的应用程序,这取决于您选择代码优先还是数据库优先。

程序创建后,右键单击Models文件夹,并选择“添加”->“新建项”。在右上角搜索框中键入”实体“,从搜索结果中选择”ADO.NET实体数据模型“。将文件名改为”BookModel.edmx“。现在可以通过向导建立数据库连接:

  1. 选择“从数据库生成”;
  2. 点击“新建连接”按钮;
  3. 在列表中选择Microsoft SQL Server,并点击“继续”;、
  4. 在连接属性对话框的服务器名称中选择你的SQL Express数据库;
  5. 连接后在数据库的下拉框中选择由MVC自动创建的数据库中最后一个表,然后点击“确定”。

* 译者注:请在步骤3的服务器名中输入.\SQLEXPRESS,步骤4中选择的应该是tempdb数据库,不知道是否在之前有前提我没有看到,当然下面所说的“Book”表也是不存在的,但是这个章节的操作有些是行不通的。

点击下一步更新Web.Config中的SQLExpress连接字符串。现在在数据库选择对话框中展开表节点并选择“Book”表。

点击“完成”之后,将会在Models目录下创建新的实体图。在创建控制器之前必须先对解决方案进行编译。项目构建完成,就像先前“代码优先”的例子中做得那样,右键单击控制器文件夹,选择“添加”->”控制器”。

使用这种方法创建的控制器,依然会有“Book”模型类,数据上下文类以及以及包含数据库连接的实体实例。

在未来的秘诀中我们将使用代码优先的方法,手工操作数据库中的表,让更多的注意力集中到MVC本身。

参考信息

ADO.NET Entity Framework Overview

[转载]MVC与轻量化的WEB开发模型(1)

mikel阅读(1226)

MVC与轻量化的WEB开发模型(1) – imfunny – 博客园.

提到MVC的时候总会有人想到ASP.NET MVC。其实倒不是,MVC更多的是一种思想。而ASP.NET MVC只是把这些给具体的实现了而已。MVC模式的缺点是由于它没有明确的定义,所以完全理解MVC模式并不是很容易。如果想看下MVC的一些理论知识, 可以看下这篇。http://zh.wikipedia.org/wiki/MVC

而流程侧如下。

OK,举例说明什么是MVC.

1:去商店买东西,付款拿到东西走人。

2:在有的地方可以付款,然后拿小票,然后再去买东西走人。

付款到取货的流程就是控制器。这两种形式其实很贴近与WebForm和Mvc的现实模型。第一种任何地方都可以付然后直接取货,第二种统一到一起进行支付然后有小票发货。

尽管有许多人都捍卫着WebForm或者ASP.NET MVC,争辩到底那种方式好或者不好,都是以偏概全,因为条条大路通罗马。选择你自己的支付方式就行了。求同存异。现实中也没见的上面的两种支付方法灭绝。

网上说的很多WebForm的缺点,比如依赖HttpContent,难以单元测试,ViewState。现在这些早就被人解决了,webform 依然可以进行mock,ViewState也可以关闭。而个人认为WebForm的缺点就是曾经看过了一个系统,后台aspx文件800多个,于是打开后 台目录哥头晕了。

首先看下其他的语言对于mvc的web开发模型是如何设计的。为什么不使用ASP.NET MVC,可以看下本文最下边。

ROR(Ruby on Rails)的。这个几乎是所有mvc的鼻祖。ASP.NET MVC就是这个的C#版。

1
2
3
4
class IndexController < ApplicationController
def Index
end
end

然后在 app\Views\Index\Index.rhtml 建立 Hello, world!

Ruby Sinatra的编码结构

get '/Index' { "Hello, world!" }

Python django的编码结构

from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world!")

Python bottle的编码结构

import bottle
app = bottle.Bottle()
@app.route('/index')
def index():
return "Hello, world!"
if __name__ == "__main__":
app.run()

看了那么多语言的表达。其实还是Sinatra和bottle表达的清晰点。相信很容易选择那种模型来做开发,直观的代码表达其实是件很重要的事情。

net其实有一个框架,叫做Nancy。地址在这里。https://github.com/NancyFx/Nancy。很多大牛在开发维护。也是个不错的项目。可以比拟与spring.net.

它的编码结构是这样的。想玩下的自己去下吧。

public class Module : NancyModule
{
public Module()
{
Get["/greet/{name}"] = x => {
return string.Concat("Hello ", x.name);
};
}
}

于是需求已经很明确了。
1.非常的高效。具备很好的可开发性。
2.方便测试代码。可以自由的Mock测试代码,最好能够自动单元测试。
3.代码表达很清晰。最好是Python bottle或者Sinatra那种,不需要动脑筋就知道代码在表达什么。
4.无需配置RouteMap,简单的路由表达。
5.支持IIS6,7,7.5,无需改动支持经典模式和集成模式,方便简单。(比如凡客怪异的url,可以用google搜索下“凡客 .mvc”就知道了。)
6.良好的插件机制。
7.实现上面所有的。

有了需求以及知道想要什么,一切都变得简单了,篇2就开始一点点的从新制造一个轻量化的轮子吧。实施上一个mvc结构的200行代码就over了。

题外话:为什么不使用ASP.NET MVC。。

ASP.NET MVC其实并不完美的原因在于,第一太大了,第二太慢了,特别是第一次打开,简直都无敌了。第三Ruby on Rails的Route都已经很糟糕了,结果ASP.NET MVC很生硬的搬过来了,继续糟糕,RouteMap太生硬了。比如/User/Content/View/1,必须要借助与RouteTable来管理 路由请求,囧爆了。而在Python bottle侧就是@app.route(‘/User/Content/View/:id’) ,Nancy就可以/User/Content/View/{id}这些可以直接定义在方法里来表达以及获取值。第四就是兼容性不够好。比如对于iis经 典模式的支持。

所以ASP.NET MVC尽管很好,但是有些缺点也很致命。每个人都有每个人的理由,求同存异。但是mvc的思想,却很伟大。如果不正确,请指教。

[原创]EasyUi的格式化Form表单中的日期显示格式

mikel阅读(1612)

遇到的问题是,弹出window中的date格式显示为“2011-12-03T23:23:02”,需要格式化为“2011-12-03  23:23”,于是查询了EasyUI的Form文档,发现Form没有获取Form组件的方法

开始在组件的formatter中加入formatterDate函数来解决,发现不会被触发,继续分析发现form数据是动态AJAX异步加载的,所以需要再加载成功后再根据id取值,然后替换掉原来的值

这样实现代码如下:

 //格式化form中的显示日期
 function formatterformdatetime(id) {
     var val = $(id).val();
     //alert(val);
     if (val) {
         return $(id).val(formatterdatetime(val));
     } else {
     return '';
     }
 }
$(function(){
        $('#track-form').form({
            onLoadSuccess: function(data) {
                //formattertime
                formatterformdatetime('#createDate');
            }
        }); 
});

[转载]使用MvcMiniProfiler调试ASP.NET MVC网站性能

mikel阅读(1002)

[转载]使用MvcMiniProfiler调试ASP.NET MVC网站性能 – L.Qiu – 博客园.

什么是MvcMiniProfiler?

一款由stackoverflow.com团队开发,专门针对ASP.NET MVC站点进行性能调试的工具,同时,其中的MvcMiniprofiler.EntityFramework组件,能直接输出当前页面执行了哪些SQL语句。

包括以下核心组件:

  • MvcMiniProfiler
  • MvcMiniProfiler.EntityFramework

如何安装?

一、环境准备

  • Visual Studio 2010
  • ASP.NET MVC项目
  • 如果需要调试EF,建议升级到Entity Framework 4.2

二、安装

推荐使用NuGet方式进行安装。推荐重典的文章:NuGet安装及简单使用

  • 第一步:在引用上右键选择“Manage NuGet Packages”
  • 第二步:Online搜索miniprofiler
    安装MiniProfiler、MiniProfiler.EF、MiniProfiler.MVC3,同时会自动安装依赖组件:WebActivator, 同时也会自动在项目里面添加代码文件:MiniProfiler.cs
  • 第三步:修改代码使MvcMiniProfiler生效

    在global.cs的Application_Start事件里面增加代码: MvcMiniProfiler.MiniProfilerEF.Initialize();
    修改View的layout文件,在head区域增加如下代码:@MvcMiniProfiler.MiniProfiler.RenderIncludes()

使用

如果安装步骤一切顺利的话,打开站点的时候,就可以在左上角看到页面执行时间了,点开可以看 到更详细的信息,如果有SQL的话,还会显示SQL语句信息,非常的方便。 页面上如果有ajax请求,也会同时显示到左上角。如果左上角显示红色提示,则表示可能存在性能问题需要处理:

点开SQL部分,可以看到详细的SQL语句


标记为duplicate的部分,代表在一次请求当中,重复执行了查询,可以优化。

总结

MvcMiniProfiler确实是一款简便易用的工具,适合进行代码层面和部分SQL层面的优化。在某些方面肯定不能替代像SQL Profiler、.Net profiler、Windbg之类的工具,个人感觉其优势在于:

  • 使用简便
  • 快速定位问题
  • 直观、明了

[转载]ASP.NET MVC3 20个秘方-(13)使用Ajax Helper 提高用户体验

mikel阅读(999)

[转载]【译】MVC3 20个秘方-(13)使用Ajax Helper 提高用户体验 – 技术弟弟 – 博客园.

问题

当你点击链接时,整个的网页都被重新加载。尤其是你仅仅一小点内容需要被更新时,这将被感觉是一个很慢的过程。

解决方案

更新之前创建的HTML.ActionLink 去调用ajax 帮助类。Ajax.ActionLink 仅仅去重新加载那些发生变化的内容。

讨论

MVC提供了几个给力的帮助类。到目前为止,这本书中已经广泛的应用了HTML Helper。在过去创建的所有view中,HTML helper至少都使用过一次。在这个秘方中,我们将使用AjaxHelper类替换掉Book/Index中的HtmlHelper 类。

实现Ajax需要一点额外的设置才可以使用。通常情况下我发现这个额外的工作,可以打消开发人员使用它的念头。我要让大家知道,额外的安装设置是值得的,因为带来的好处是获得了更好的用户体验,这是非常值得努力去做的。

步骤从web.config开始。2个关键的地方要被设置成true. ClientValidationEnabled 和UnobtrusiveJavaScriptEnabled。

译者:原书中代码引入了整个web.config文件。我们只需要到appSettings节点下即可找到这两个keys。

  <appSettings>
    <add key="webpages:Version" value="1.0.0.0" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
  </appSettings>

接下来的步骤是我们要引入几个JavaScript 文件。我们要在里shared 的layout文件夹里完成这件事,因为几乎我们创建所有的view时都会引用它(布局模板)。在Views/Shared /_Layout.cshtml 文件的<head>标签中。我们引入2个JavaScript 文件,代码如下:

<head>
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")"type="text/javascript"></script>
</head>

这些文件被自动的包含在基础MVC3应用程序中。(译者:你可以从scripts文件夹中找到他们)。以上的步骤完成AJAX的核心配置。接下来, 我们要更新Book/index view。在下边的例子里,三个filter link和sortable header link将用Ajax.ActionLink 替换Html.ActionLink.代码如下:

@model PagedList.IPagedList<MvcApplication.Models.Book>
@if (IsAjax)
{
    Layout = null;
}
<h2>
    Title</h2>
<p>
    @Html.ActionLink("Create New", "Create")
</p>
<p>
    Show:
    @if (ViewBag.CurrentFilter != "")
    {
        @Ajax.ActionLink("All", "Index",
                            new
                            {
                                sortOrder = ViewBag.CurrentSortOrder,
                                Keyword = ViewBag.CurrentKeyword
                            },
                            new AjaxOptions { UpdateTargetId = "main" })
    }
    else
    {
        @:All
        }
    &nbsp; | &nbsp;
    @if (ViewBag.CurrentFilter != "NewReleases")
    {
        @Ajax.ActionLink("New Releases", "Index", new
                        {
                            filter = "NewReleases",
                            sortOrder = ViewBag.CurrentSortOrder,
                            Keyword = ViewBag.CurrentKeyword
                        },
                        new AjaxOptions { UpdateTargetId = "main" })
    }
    else
    {
        @:New Releases
        }
    &nbsp; | &nbsp;
    @if (ViewBag.CurrentFilter != "ComingSoon")
    {
        @Ajax.ActionLink("Coming Soon", "Index", new
                        {
                            filter = "ComingSoon",
                            sortOrder = ViewBag.CurrentSortOrder,
                            Keyword = ViewBag.CurrentKeyword
                        },
                        new AjaxOptions { UpdateTargetId = "main" })
    }
    else
    {
        @:Coming Soon
        }
</p>
@using (Html.BeginForm())
{
    @:Search: @Html.TextBox("Keyword")<input type="submit" value="Search" />

}
@Html.Partial("_Paging")
<table>
    <tr>
        <th>
            @Ajax.ActionLink("Title", "Index", new
                            {
                                sortOrder = ViewBag.TitleSortParam,
                                filter = ViewBag.CurrentFilter,
                                Keyword = ViewBag.CurrentKeyword
                            },
                            new AjaxOptions { UpdateTargetId = "main" })
        </th>
        <th>
            @Ajax.ActionLink("Isbn", "Index", new
                            {
                                sortOrder = ViewBag.IsbnSortParam,
                                filter = ViewBag.CurrentFilter,
                                Keyword = ViewBag.CurrentKeyword
                            },
                            new AjaxOptions { UpdateTargetId = "main" })
        </th>
        <th>
            Summary
        </th>
        <th>
            @Ajax.ActionLink("Author", "Index", new
                            {
                                sortOrder = ViewBag.AuthorSortParam,
                                filter = ViewBag.CurrentFilter,
                                Keyword = ViewBag.CurrentKeyword
                            },
                            new AjaxOptions { UpdateTargetId = "main" })
        </th>
        <th>
            Thumbnail
        </th>
        <th>
            @Ajax.ActionLink("Price", "Index", new
                            {
                                sortOrder = ViewBag.PriceSortParam,
                                filter = ViewBag.CurrentFilter,
                                Keyword = ViewBag.CurrentKeyword
                            },
                            new AjaxOptions { UpdateTargetId = "main" })
        </th>
        <th>
            @Ajax.ActionLink("Published", "Index", new
                            {
                                sortOrder = ViewBag.PublishedSortParam,
                                filter = ViewBag.CurrentFilter,
                                Keyword = ViewBag.CurrentKeyword
                            },
                            new AjaxOptions { UpdateTargetId = "main" })
        </th>
        <th>
        </th>
    </tr>
    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Title)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Isbn)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Summary)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Author)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Thumbnail)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Price)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Published)
            </td>
            <td>
                @Html.ActionLink("Edit","Edit", new { id = item.ID }) |
                @Html.ActionLink("Details","Details", new { id = item.ID }) |
                @Html.ActionLink("Delete","Delete", new { id = item.ID })
            </td>
        </tr>
    }
</table>
@Html.Partial("_Paging")

译者:上边代码标绿的地方就是我们更新的地方。

我们做的关键的事就是在ActionLink的最后一个参数添加了AjaxOptions。 这意味着一旦用户点击了这个AJAX link,AJAX请求的结果将会更新id 是“main”的html元素。如果你看看share文件夹中早期我们修改的layout文件,你会注意到有一个<div>的id 是“main”。实际上,这个div就是@Renderbody()的容器,它是一个view输出的地方。

另外一个重要的事就是我们在view的顶端加了一个AJAX是否完成的检测。如果请求通过AJAX完成,layout设 置成null。这是一个非常重要的因素,因为如果它没完成,Ajax请求的结果将会包含不仅仅是view的result,也会包含整个layout,而没 必要再去替换掉layout了。

为了完成这个示例,share文件夹下的_Paging也要使用Ajax helper更新,代码如下:

<p>
    @if (Model.HasPreviousPage)
    {
        @Ajax.ActionLink("<< First", "Index", new
                        {
                            page = 1,
                            sortOrder = ViewBag.CurrentSortOrder,
                            filter = ViewBag.CurrentFilter
                        },
                        new AjaxOptions { UpdateTargetId ="main" })
        @Html.Raw("&nbsp;");
        @Html.ActionLink("< Prev", "Index", new
                        {
                            page = Model.PageNumber - 1,
                            sortOrder = ViewBag.CurrentSortOrder,
                            filter = ViewBag.CurrentFilter
                        },  new AjaxOptions { UpdateTargetId ="main" })
    }
    else
    {
        @:<< First
        @Html.Raw("&nbsp;");
        @:< Prev
    }
    &nbsp;&nbsp;
    @if (Model.HasNextPage)
    {
        @Ajax.ActionLink("Next >", "Index", new
                        {
                            page = Model.PageNumber + 1,
                            sortOrder = ViewBag.CurrentSortOrder,
                            filter = ViewBag.CurrentFilter
                        },  new AjaxOptions { UpdateTargetId ="main" })
        @Html.Raw("&nbsp;");
        @Ajax.ActionLink("Last >>", "Index", new
                        {
                            page = Model.PageCount,
                            sortOrder = ViewBag.CurrentSortOrder,
                            filter = ViewBag.CurrentFilter
                        },  new AjaxOptions { UpdateTargetId ="main" })
    }
    else
    {
        @:Next >
        @Html.Raw("&nbsp;")
        @:Last >>
    }
</p>

现在,当用户点击一个link 改变book 列表时,整个的页面不会被重新载入并且仅仅是图书列表被更新。这提供了一个更好、更快的用户体验。

而且,如果客户端不支持javascript(例如,一个搜索引擎访问),这个link将像以前一样工作。它将重新载入整个页面。

另请参见

AjaxHelper

[转载]Asp.net MVC源码分析--Asp.net MVC与Ninject.MVC集成分析

mikel阅读(816)

[转载]Asp.net MVC源码分析–Asp.net MVC与Ninject.MVC集成分析 – 十一月的雨 – 博客园.

在之前的文章中我们分析了DependencyResolver 与 Service location. 可以利用DependencyResolver 来注册我们自己的IResolver实现,从而改变框架的行为.在Niject.MVC 中正是利用这个机制来实现了一套Service location机制,来创建Controller.

Niject.MVC 源码的下载地址是: https://github.com/ninject/ninject.web.mvc

——————————————————————————————

首先我们找到NinjectMVC3.cs 文件,所有引入Niject.MVC dll 的ASP.NET MVC项目都需要这个类

View Code

 1 #if NUGET
 2 [assembly: WebActivator.PreApplicationStartMethod(typeof(SampleApplication.App_Start.NinjectMVC3), "Start")]
 3 [assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(SampleApplication.App_Start.NinjectMVC3), "Stop")]
 4 
 5 namespace SampleApplication.App_Start
 6 {
 7     using System.Reflection;
 8     using Microsoft.Web.Infrastructure.DynamicModuleHelper;
 9     using Ninject;
10     using Ninject.Web.Mvc;
11 
12     public static class NinjectMVC3 
13     {
14         private static readonly Bootstrapper bootstrapper = new Bootstrapper();
15 
16         /// <summary>
17 /// Starts the application
18 /// </summary>
19         public static void Start() 
20         {
21             DynamicModuleUtility.RegisterModule(typeof(OnePerRequestModule));
22             DynamicModuleUtility.RegisterModule(typeof(HttpApplicationInitializationModule));
23             bootstrapper.Initialize(CreateKernel);
24         }
25         
26         /// <summary>
27 /// Stops the application.
28 /// </summary>
29         public static void Stop()
30         {
31             bootstrapper.ShutDown();
32         }
33         
34         /// <summary>
35 /// Creates the kernel that will manage your application.
36 /// </summary>
37 /// <returns>The created kernel.</returns>
38         private static IKernel CreateKernel()
39         {
40             var kernel = new StandardKernel();
41             RegisterServices(kernel);
42             return kernel;
43         }
44 
45         /// <summary>
46 /// Load your modules or register your services here!
47 /// </summary>
48 /// <param name="kernel">The kernel.</param>
49         private static void RegisterServices(IKernel kernel)
50         {
51             kernel.Load(Assembly.GetExecutingAssembly());
52         }        
53     }
54 }
55 #endif

我们看到当Assembly 加载后会调用WebActivator 的StartMethod方法来,启动NinjectMVC3.Start方法这个方法中调用了bootstrapper.Initialize方法.

View Code

 1   public class Bootstrapper: IBootstrapper
 2     {
 3         /// <summary>
 4 /// The ninject kernel of the application
 5 /// </summary>
 6         protected static IKernel kernelInstance;
 7 
 8         /// <summary>
 9 /// Gets the kernel.
10 /// </summary>
11         [Obsolete("Do not use Ninject as Service Locator")]
12         public IKernel Kernel
13         {
14             get { return kernelInstance; }
15         }
16 
17         /// <summary>
18 /// Starts the application.
19 /// </summary>
20 /// <param name="createKernelCallback">The create kernel callback function.</param>
21         public void Initialize(Func<IKernel> createKernelCallback)
22         {
23             if (kernelInstance != null)
24             {
25                 throw new InvalidOperationException("Already Initialized!");
26             }
27 
28             kernelInstance = createKernelCallback();
29 
30             kernelInstance.Bind<IResolutionRoot>().ToConstant(kernelInstance);
31             kernelInstance.Bind<IDependencyResolver>().To<NinjectDependencyResolver>();
32             kernelInstance.Bind<IFilterProvider>().To<NinjectFilterAttributeFilterProvider>();
33             kernelInstance.Bind<IFilterProvider>().To<NinjectFilterProvider>();
34             kernelInstance.Bind<RouteCollection>().ToConstant(RouteTable.Routes);
35             kernelInstance.Bind<HttpContext>().ToMethod(ctx => HttpContext.Current).InTransientScope();
36             kernelInstance.Bind<HttpContextBase>().ToMethod(ctx => new HttpContextWrapper(HttpContext.Current)).InTransientScope();
37             kernelInstance.Bind<ModelValidatorProvider>().To<NinjectDataAnnotationsModelValidatorProvider>();
38 
39             ModelValidatorProviders.Providers.Remove(ModelValidatorProviders.Providers.OfType<DataAnnotationsModelValidatorProvider>().Single());
40             DependencyResolver.SetResolver(CreateDependencyResolver());
41             RemoveDefaultAttributeFilterProvider();
42         }
43 
44         /// <summary>
45 /// Initializes a HttpApplication instance.
46 /// </summary>
47 /// <param name="httpApplication">The HttpApplication instance.</param>
48         public void InitializeHttpApplication(HttpApplication httpApplication)
49         {
50             kernelInstance.Inject(httpApplication);
51         }
52 
53         /// <summary>
54 /// Releases the kernel on application end.
55 /// </summary>
56         public void ShutDown()
57         {
58             if (kernelInstance != null)
59             {
60                 kernelInstance.Dispose();
61                 kernelInstance = null;
62             }
63         }
64 
65         /// <summary>
66 /// Creates the controller factory that is used to create the controllers.
67 /// </summary>
68 /// <returns>The created controller factory.</returns>
69         private static IDependencyResolver CreateDependencyResolver()
70         {
71             return kernelInstance.Get<IDependencyResolver>();
72         }
73 
74         /// <summary>
75 /// Removes the default attribute filter provider.
76 /// </summary>
77         private static void RemoveDefaultAttributeFilterProvider()
78         {
79             var oldFilter = FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider);
80             FilterProviders.Providers.Remove(oldFilter);
81         }
82     }

在这Initialize方法中向kernel容器注入了很多接口的实现.并且向DependencyResolver中注册了Ninject的IDependencyResolver实现

DependencyResolver.SetResolver(CreateDependencyResolver());

最后我们就可以向Ninject注入所有MVC 框架中依赖DependencyResolver获取接口的实现.

并且当我们的Controller 的构造函数中有接口参数,并且在Ninject有注册的话,也可以顺利的创建Controller的参数中的接口(因为所有Controller的创建都通过Ninject),这样我们就可以把Controller中的一些业务行为抽取出来创建独立的类(业务层),从而划分出更清晰的类的层次结构和设计.

例如:

View Code

 1 public class AccountController : Controller
 2 {
 3 
 4   private IAccountManater _accountManager;
 5 
 6   public AccountController (IAccountManater accountManager)
 7 
 8   {
 9 
10     _accountManager = accountManager;
11 
12   }
13 
14 [HttpPost]
15 public ActionResult LogOn(LogOnModel model, string returnUrl)
16 {
17 
18   if(_accountManager.Has(model))
19 
20     return view("ok");
21 
22   else
23 
24     return view("error");
25   }
26 
27 }

这时只要我们在Application_Strat 中向Iinject容器中注册IAccountManager 的实现AccountController就可以使用了.

[转载]使用 Jquery 来实现可以输入值的下拉选单(一)

mikel阅读(1060)

[转载]使用 Jquery 来实现可以输入值的下拉选单(一) – 一条小龙 – 博客园.

最近案子中,需要使用下拉选单,但问题是,里面选项都会有各 其他:,然後 可以 让 user 在输入值

上网 找了一下,有一堆现成的控件,可是 现成的 我要去了解,来结合我现在 系统来应用,要花不少时间,这个时间 跟我自己 搞一个成本 应该差不多

那我还不如 自己 搞一个,比较能了解 怎麽运作,後面就更容易加以运用了。

我的目标是,要把 这个 作成一个控件来使用,并要降低外部程式使用的耦合性,也就是 外部程式 使用上所需的必要条件要尽量减少,免得一忘记加什麽设定,程式 就挂了。

如有可能 甚至希望,只会需要引用一个 JQuery 其他 JavaSciprt 都由程式 来产生。

最後是希望能结合 之前讲得动态控件 来使用,今天 我就先研究一下,用出了下面这个 html 做的雏型,来先行测试一下可行性,确认无误在开始动工改成 ASP.NET 的控件 。

这程式 有几个 重要问题,需要注意的:

下拉选单的触发方式、下拉选单的内容如何绘出,选单事件触发的抓取、抓取到选择事件後值要存在哪里

上述问题解决後,後面 都要用 ASP.NET 的方式来重新撰写,所以在设计雏型时,需注意其能否应用在 ASP.NET 上

构思如下:

这我的打算就是设计一个 button 藉由其 OnClick 事件来触发,到时会由 JQuery 抓取 ASP.NET 动态产生的选单阵列,来动态产生选单,

产生的选单,要能设定三各事件 mouSEOver mouSEOut click,前两各 是为了美观,这样 user 才知道 有在动作,click 事件触发後,

将选取到的值储存到 asp.net 的 server 控件 TextBox 中,如此 在 PostBack 就能把值 传回 server 端 来处理。

 1     <head>  
 2         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 3         <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js" ></script>  
 4         <title>使用 Jquery 来实现可以输入值的下拉选单(一)</title>  
 5      
 6      
 7         <script type="text/javascript">
 8             $(document).ready(function () {
 9                 //动画速度  
10                 var speed = 500;
11 
12                 //选单的相关处理事件
13                 $("#divPop div").live("mouseover mouseout click", function (event) {
14                     if (event.type == "mouseover") {
15                         //$(this).addClass(‘highlight’);
16                         $(this)[0].style.backgroundColor = '#E6F5FA';
17                     }
18                     if (event.type == "mouseout") {
19                         //$(this).removeClass("highlight");
20                         $(this)[0].style.backgroundColor = '#DDFFDD';
21                     }
22                     if (event.type == "click") {
23                         var inID = $("#btnDDL").get(0).getAttribute("inputid");
24                         //alert($(this).html());
25                         $("#" + inID).val($(this).html());
26                     }
27                 });
28                 //动态产生下拉选单的选项,後面 要从 array 中读取产生选单
29                 $("#divPop").append("<div>test1</div>");
30                 $("#divPop").append("<div>test2</div>");
31 
32                 //绑定事件处理  
33                 $("#btnDDL").click(function (event) {
34                     //取消事件冒泡  
35                     event.stopPropagation();
36                     //设置弹出层位置  
37                     var offset = $(event.target).offset();
38                     //alert($(event.target).width());
39                     var inID = $(this).get(0).getAttribute("inputid");
40                     //依據 input 跟 button 寬度來設定 下拉選單的寬度
41                     $("#divPop")[0].style.width = ($("#" + inID).width() + $(this).width() + 10) + "px";
42                     //单击空白区域隐藏弹出层  
43                     $(document).click(function (event) { $("#divPop").hide(speed) });
44                     //设定下拉选单显示的位置
45                     $("#divPop").css({ top: offset.top + $(event.target).height() + 10 + "px", left: offset.right });
46                     //切换弹出层的显示状态  
47                     $("#divPop").toggle(speed);
48                 });
49             });
50 
51         </script>  
52      
53     </head>  
54     <body>  
55         <div>  
56             <br /><br /><br />  
57             <input name="txtKey" type="text" maxlength="30" size="30" id="txtKey" style="Padding:2px;" /><button id="btnDDL" inputid="txtKey" >▼</button>  
58         </div>  
59               
60         <!-- 弹出层 -->  
61         <div id="divPop" style="background-color: #DDFFDD; border: solid 1px #000000; position: absolute; display:none;  
62             width: 300px; height: 100px;">  
63             
64         </div>  
65     </body>  
66     </html>

这里面 还有各 想解决的问题,就是要让 divPop 也能动态产生…

[转载]Android 4.0发布X86版本

mikel阅读(1487)

[转载]Android 4.0发布X86版本 – 开源文档社区 – 博客园.

Android 4.0,来见见你公公X86

当不同辈分的人凑到一起而没有任何争吵难道不是一件非常美妙的事吗? google 的Ice Cream
Sandwich的x86版本最终准备面向开发者了,而且他承诺确实要做这样的事: 同有33年历史的intel /amd
架构玩得很high而不是仅仅是那些从arm来的年轻的暴发户。这个联盟目前还不是非常和谐:网络和照相功能还不能用,同时wi-fi,声音,和硬件加速目前也只是amd-only的。

然而,那些没有受到这些鸡毛蒜皮的事影响的开发者,能够通过下面的链接下载源代码:

sourceAndroid-x86.orgAndroid-x86(Google Groups)

本文翻译自:http://www.engadget.com/2011/12/01/android-4-0-meet-your-granddad-x86/