目录

壹 、方案框架结构

  1. ASP.NET
    MVC搭建项目后台UI框架—壹 、后台主框架
  2. ASP.NET
    MVC搭建项目后台UI框架—② 、菜单特效
  3. ASP.NET
    MVC搭建项目后台UI框架—叁 、面板折叠和进展
  4. ASP.NET
    MVC搭建项目后台UI框架—④ 、tab多页签援救
  5. ASP.NET
    MVC搭建项目后台UI框架—伍 、德姆o演示Controller和View的相互
  6. ASP.NET
    MVC搭建项目后台UI框架—⑥ 、客户保管(添加、修改、查询、分页)
  7. ASP.NET
    MVC搭建项目后台UI框架—柒 、总括报表
  8. ASP.NET
    MVC搭建项目后台UI框架—捌 、将View中选取的多少行中的有个别数据传入到Controller中
  9. ASP.NET
    MVC搭建项目后台UI框架—九 、服务器端排序

  本方案架构很简短——它用3个Web服务来包装ASP.NET
2.0提供者并且为远程客户揭穿该证据管理,你居然还是能够在该架构中加上有的失去的法力。然后,在提供四个加上的用户接口和百科凭证管理经验的同时,使用三个Windows表单应用程序来费用该Web服务。该Web服务配置文件将含有特定于该证据存款和储蓄的下令。然则,那确实意味着全体由该Web服务管理的应用程序都将得以共享那几个指令。

紧接着在此以前未写完的存在延续,本篇,笔者将执教在此UI框架仲阳ASP.NET
MVC4展开整合开发。效果如下:

  固然你可见初阶到尾地构建该Web服务,也正是说,首先用静态方法Roles和Membership来包装它们并定义该Web服务,作者却更欣赏一种契约驱动的主意:首先设计执行各个操作的最好接口将是何等,并且直到须要时才考虑什么达成它们。那样做能够保证由Web服务暴露的接口援助具备供给的保管职能并且还将回落该客户应用程序与别的实现细节(例如包装提供者)之间的耦合。

统计 1统计 2统计 3

   ASP.NET
2.0的三个更好的天性是它匡助Web服务接口,你能够定义并且让该Web服务揭露逻辑接口,就象类的表现一样。为此,你要求用
WebServiceBinding属性修饰你的接口并且经过WebMethod属性来暴光单个的接口方法。然后,你将有四个派生于那个接口的类并贯彻该接口,而且编写翻译器将须要你帮助该接口的具有办法。

此地,小编将增进和修改用了五个不一样的视图,当然也能够把添加和修改放到同3个视图中,不过要写一些政工逻辑代码来分别当前调用的是修改依旧增进,依据添加和改动的不比,而对界面举行差别的操作。

  为了管住和互相于凭证存款和储蓄和Web服务配置,作者定义了几个接口-IApplicationManager,IMembershipManager,IPasswordManager,IroleManager和IUserManager。

添加控制器Customer,关于立异操作,作者就只可以想吐槽一下NHibernate,他妹的,每一回都要先load二回,然后再Update()贰次,假若你直接save,它就把您表中有,但是界面上并未传过来的值全部翻新为null了,比较之下EF就好多了。

  (一) IApplicationManager

统计 4统计 5

  该IApplicationManager接口展现于所附源码中的列表2,允许管理员删除一钦赐的应用程序-也便是说,从数据库中剔除全数到它的参照并且删除它的富有用户和剧中人物。IApplicationManager允许从存储中除去全体的应用程序,并且它能回到在该存款和储蓄中的全部应用程序的多个列表。注意,那一个接口作为二个内部的接口被定义-public或internal可知性修饰词对Web服务接口都以空洞的。该接口上的种种方法用
WebMethod属性加以修饰并有二个该措施的简要描述。其它,存取凭证存款和储蓄的享有办法都棉被服装置为运用事务处理。那样以来,二种操作-如剔除一应用程序和创办一用户将在互相完全切断的事态下实施,从而确认保证了如删减全部用户等复杂操作的原子性。.NET
2.0中的Web服务只好运维三个新工作,而且它是由WebMethod属性的TransactionOption属性来决定的。最后一点是把
WebServiceBinding属性应用于接口上。那就内定该接口是二个客户和服务都能绑定到的Web服务接口。为了把该接口以三个WSDL契约情势暴光给外界,你必要利用一个shim类。这么些shim类的规划是少不了的,因为您不可能把1个接口作为一Web服务揭破,而且你也不能够在其上选择WebService属性。这一个shim类还将经由Web瑟维斯属性为该接口命名空间定义。下边包车型地铁代码突显了
IApplicationManagerShim抽象类的概念。

 public class CustomerController : Controller
    {
 private string message = "<script>frameElement.api.opener.hidePublishWin('{0}', '{1}','{2}'); </script>"; //消息,是否关闭弹出窗,是否停留在当前分页(0,1)

        #region 客户管理主页
        public ActionResult Index()
        {
            return View();
        }

        /// <summary>
        /// 客户列表
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult List(CustomerFilter filter)
        {
            filter.PageSize = int.MaxValue;
            var dataSource = CustomerInfo.GetByFilter(filter);

            List<CustomerInfo> queryData = dataSource.ToList();

            var data = queryData.Select(u => new
            {
                ID = u.ID,
                CusCode = u.CusCode,
                CusName = u.CusName,
                BusssinessType = u.BusssinessType.GetDescription(false),
                Balance = u.Balance,
                CreditAmount = u.CreditAmount,
                Status = u.Status.GetDescription(false),
                Country = u.Country,
                CompanyName = u.CompanyName,
                Delivery = GetDeliveryList(u.ExpressCurInfoBy)

            });

            //构造成Json的格式传递
            var result = new { iTotalRecords = queryData.Count, iTotalDisplayRecords = 10, data = data };
            return Json(result, JsonRequestBehavior.AllowGet);
        }
        #region 添加客户
        /// <summary>
        /// 添加客户
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public ActionResult AddCustomer()
        {
            ViewBag.Title = "添加客户";
            return View();
        }

        /// <summary>
        /// 添加客户
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult AddCustomer(CustomerInfo info)
        {
            string msg = string.Empty;
            if (ModelState.IsValid)
            {
                try
                {
                    info.Save();
                    msg = "添加客户成功。";
                }
                catch (Exception ex)
                {
                    msg = "添加客户失败!" + ex.Message;
                    ViewBag.Msg = string.Format(message, msg, false,"0");
                }
                ViewBag.Msg = string.Format(message, msg, true,"0");
            }
            return View();
        }
        #endregion

        #region 修改客户
        /// <summary>
        /// 修改客户
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public ActionResult UpdateCustomer(int id)
        {
            ViewBag.Title = "修改客户";
            var result = CustomerInfo.Load(id);

            return View(result);
        }

        /// <summary>
        /// 修改客户
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult UpdateCustomer(CustomerInfo info)
        {
            string msg = string.Empty;
            if (ModelState.IsValid)
            {
                try
                {
                    info.Update();
                    msg = "修改客户成功。";
                }
                catch (Exception ex)
                {
                    msg = "修改客户失败!" + ex.Message;
                    ViewBag.Msg = string.Format(message, msg, false,"1");
                }
                ViewBag.Msg = string.Format(message, msg, true,"1");
            }
            return View();
        }
        #endregion
    }

[WebService(Name=”IApplicationManager”,
Namespace=”http://CredentialsServices“,
Description=”IApplicationManager is used to manage
applications. This web service is only
the definition of the interface. You
cannot invoke method calls on it.”)]
abstract class IApplicationManagerShim : IApplicationManager{
 public abstract void DeleteApplication(string application);
 public abstract string[] GetApplications();
 public abstract void DeleteAllApplications();
}

View Code

  因为IApplicationManagerShim是多个类,所以您能够把它揭穿为贰个Web服务。因为它是一抽象类且持有办法被定义为架空方法,所以不需求(也不可能)实现其余措施。为了使其看起来就象该接口,IapplicationManagerShim把WebService属性的性格名设置为
IApplicationManager(代替缺省的类名)。今后,你能够应用IApplicationManager.asmx文件来揭穿该接口。

添加视图Index

<%@ WebService Language=”C#”
CodeBehind=”~/App_Code/IApplicationManagerShim.cs”
Class=”IApplicationManagerShim”%>

统计 6统计 7

  今后,假若你浏览到IApplicationManager.asmx页面,你就晤面到该接口定义。你能够利用WSDL.exe的serverInterface选项来把接口定义输入到客户端或任何其它想绑定到该接口定义上的劳务。

@{
    ViewBag.Title = "客户信息";
}
<link href="~/libs/DataTables-1.10.6/media/css/jquery.dataTablesNew.css" rel="stylesheet" />
<script src="~/libs/DataTables-1.10.6/media/js/jquery.dataTables.min.js"></script>
<script src="~/Scripts/DataTablesExt.js"></script>
<script type="text/javascript">
    //弹出框  
    var addDG, updateDG, matchDG;
    var w = 424, h = 520; //宽,高
    //添加记录
    function showPublishWin() {
        addDG = new $.dialog({
            id: "AddChannel",
            title: "添加客户",
            content: "url:/Customer/AddCustomer",
            width: w,
            height: h,
            max: false,
            min: false,
            lock: true,
            close: true,
            btnBar: false
        });
        addDG.show();
    }
    //修改记录
    function modifyRecord(id) {
        updateDG = new $.dialog({
            id: "UpdateCustomer",
            title: "修改客户",
            content: "url:/Customer/UpdateCustomer/" + id,
            width: w,
            height: h,
            max: false,
            min: false,
            lock: true,
            close: true,
            btnBar: false
        });
        updateDG.show();
    }
    //隐藏弹出框
    function hidePublishWin(msg, result, isStay) {
        var icon = "success.gif";
        if (result == "False") {
            icon = "error.gif";
        }
        $.dialog({
            title: "提示",
            icon: icon,
            titleIcon: 'lhgcore.gif',
            content: msg,
            lock: true,
            ok: true
        });
        if (result != "False") {
            if (addDG) {
                addDG.close();
            }
            if (updateDG) {
                updateDG.close();
            }
            if (matchDG) {
                matchDG.close();
            }
            if (isStay == 0) {
                reloadList();
            }
            else {
                reloadListNew();
            }
        }
    }
    function matchDelivery(id) {
        matchDG = new $.dialog({
            id: "UpdateCustomer",
            title: "客户匹配",
            content: "url:/Customer/DeliveryMatching/" + id,
            width: 800,
            height: h,
            max: false,
            min: false,
            lock: true,
            close: true,
            btnBar: false
        });
        matchDG.show();
    }
    //刷新,但是停留在当前分页
    function reloadListNew() {
        var tables = $('#table_local').dataTable().api();//获取DataTables的Api,详见 http://www.datatables.net/reference/api/
        tables.ajax.reload(null,false);
    }
</script>
<script type="text/javascript">
    $(function () {
        var h = $(document).height() - 258;
        var table = $("#table_local").dataTable({
            bProcessing: true,
            "scrollY": h,
            "scrollCollapse": "true",
            "dom": 'ftr<"bottom"lip><"clear">',
            "bServerSide": false,                    //指定从服务器端获取数据  
            sServerMethod: "POST",
            sAjaxSource: "@Url.Action("List", "Customer")",
            "fnServerParams": function (aoData) {  //查询条件
                aoData.push(
                    { "name": "CusCode", "value": $("#CusCode").val() },
                    { "name": "CusName", "value": $("#CusName").val() }
                    );
            },
            columns: [{ title: "1", "visible": false, "data": "ID" },
               { "data": "CusCode", title: "客户代码" },
               { "data": "CusName", title: "客户名称" },
               { "data": "BusssinessType", title: "业务类型", width: "100" },
               { "data": "Country", title: "国家", width: "200" },
               { "data": "CompanyName", title: "公司名称", width: "200" },
               { "data": "Delivery", title: "收货商", width: "150" },
               { "data": "Balance", title: "账户余额", width: "150" },
               { "data": "CreditAmount", title: "信用额度", width: "150" },
               { "data": "Status", title: "是否启用", width: "100" },
               {
                   "data": "ID", orderable: false, title: "操作", width: "140", "render": function (data, type, row, meta) { //自定义列
                       var re = "<div style='text-align:center'><a style='visibility:visible' onclick='modifyRecord(" + data + ")'>修改</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
                       re = re + "<a style='visibility:visible' onclick='matchDelivery(" + data + ")'>匹配</a></div>";
                       return re;
                   }
               }
            ],
            paging: true,//分页
            ordering: true,//是否启用排序
            searching: true,//搜索
            language: {
                "sProcessing": "处理中...",
                lengthMenu: '每页显示:<select class="form-control input-xsmall">' + '<option value="5">5</option>' + '<option value="10">10</option>' + '<option value="15">15</option>'
                    + '<option value="20">20</option>' + '<option value="25">25</option>' + '<option value="30">30</option>' + '<option value="35">35</option>' + '<option value="40">40</option>',//左上角的分页大小显示。
                search: '搜索:',//右上角的搜索文本,可以写html标签

                paginate: {//分页的样式内容。
                    previous: "上一页",
                    next: "下一页",
                    first: "",
                    last: ""
                },

                zeroRecords: "暂无记录",//table tbody内容为空时,tbody的内容。
                //下面三者构成了总体的左下角的内容。
                info: "总共 (_PAGES_) 页,显示 _START_ -- _END_ ,共 (_TOTAL_) 条",//左下角的信息显示,大写的词为关键字。初始_MAX_ 条 
                infoEmpty: "0条记录",//筛选为空时左下角的显示。
                infoFiltered: ""//筛选之后的左下角筛选提示,
            },
            pagingType: "full_numbers"//分页样式的类型

        });
        //设置选中行样式
        $('#table_local tbody').on('click', 'tr', function () {
            if ($(this).hasClass('selected')) {
                $(this).removeClass('selected');
            }
            else {
                table.$('tr.selected').removeClass('selected');
                $(this).addClass('selected');
            }
        });
    });
    //查询 刷新
    function reloadList() {
        var tables = $('#table_local').dataTable().api();//获取DataTables的Api,详见 http://www.datatables.net/reference/api/
        tables.ajax.reload();
    }
</script>
<div class="areabx clear">
    @using (Html.BeginForm("List", null, FormMethod.Get, new { @clase = "form-inline", @role = "form" }))
    {
        <div class="areabx_header">客户信息</div>
        <ul class="formod mgt10">
            <li>客户代码:@Html.TextBox("CusCode", "", new { @class = "trade-time wid153" })</li>
            <li>客户名称:@Html.TextBox("CusName", "", new { @class = "trade-time" })</li>
            <li></li>
        </ul>
        <div class="botbtbx pdb0" style="margin-bottom: -30px;">
            <input type="button" value="添加客户" class="btn btn-primary" onclick="showPublishWin()" />
            <input type="button" value="查询" onclick="reloadList();" class="btn btn-primary">
        </div>
    }
    <div class="tob_box mgt15">
        <table id="table_local" class="display" cellspacing="0" cellpadding="0" border="0" style="width: 100%">
        </table>
    </div>
</div>

  (二) IMembershipManager

View Code

  IMembershipManager接口(见所附源码中的列表3)允许你管理用户帐户的富有地点-创立和删除用户帐户,更新用户帐户,检索用户帐户细节以及查找在一应用程序中的全体用户。

添加AddCustomer视图,在此之前集团ASP.NET
MVC的品种没有启用模型验证,界面验证代码都以温馨js写的,小编晕,那用ASP.NET
MVC干嘛呢?使用框架便是要丰裕发挥框架优秀的效应,尽恐怕飞快便捷的成本,并缩减开发职员的代码量。

  (三) IRoleManager

统计 8统计 9

  IRoleManager接口允许你管理逻辑角色的有着地点-创立和删除角色,从剧中人物中追加和删除用户以及查找在一应用程序中的全部剧中人物。

@model Core.Customer.CustomerInfo
@using ProjectBase.Utils
@Html.Raw(ViewBag.Msg)
<div class="areabx clear">
@*    <div class="areabx_header">@ViewBag.Title</div>*@
    <div class="tian_xi">
        @using (Html.BeginForm("AddCustomer", "Customer", FormMethod.Post, new { @clase = "form-inline", @role = "form", name = "from1" }))
        {
            <table width="100%" border="0" cellpadding="0" cellspacing="0">
                <tbody>
                    <tr style="height: 40px;">
                        <td style="width: 120px; text-align: right;">客户代码:</td>
                        <td>
                            @Html.TextBoxFor(x => x.CusCode, new { @class = "trade-timen", @id = "cusCode" })* @Html.ValidationMessageFor(m => m.CusCode)</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">客户名称:</td>
                        <td>
                            @Html.TextBoxFor(x => x.CusName, new { @class = "trade-timen", @id = "cusName" })* @Html.ValidationMessageFor(m => m.CusName)</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">手机:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Phone, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">电话:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Tel, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">邮箱:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Email, new { @class = "trade-timen", @id = "email" })@Html.ValidationMessageFor(m => m.Email)</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">传真:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Fax, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">国家:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Country, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">地址:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Address, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">公司名称:</td>
                        <td>
                            @Html.TextBoxFor(x => x.CompanyName, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">业务类型:</td>
                        <td>
                        @Html.DropDownListFor(x => x.BusssinessType, @Html.EnumToList(typeof(Core.Customer.Busssiness), false), new { @class = "trade-timen", style = "width:180px" })
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">是否启用:</td>
                        <td>是 @Html.RadioButtonFor(x => x.Status, "0", new { Checked = "checked", @name = "status" }) &nbsp;&nbsp;&nbsp;&nbsp;
                            否 @Html.RadioButtonFor(x => x.Status, "1", new { @name = "status" })</td>
                    </tr>
                </tbody>
            </table>
            <input type="submit" value="确定" class="popbtn1 mg">
            <input type="button" value="关闭" class="popbtn3 mg2" onclick="frameElement.api.opener.addDG.close();" />
        }
    </div>
</div>

[WebServiceBinding(“IRoleManager”)]
interface IRoleManager{
[WebMethod(…)]
void CreateRole(string application,string role);
[WebMethod(…)]
bool DeleteRole(string application,string role,bool
throwOnPopulatedRole);
[WebMethod(…)]
void AddUserToRole(string application,string userName, string role);
[WebMethod(…)]
void DeleteAllRoles(string application,bool throwOnPopulatedRole);
[WebMethod(…)]
string[] GetAllRoles(string application);
[统计,WebMethod(…)]
string[] GetRolesForUser(string application,string userName);
[WebMethod(…)]
string[] GetUsersInRole(string application, string role);
[WebMethod(…)]
void RemoveUserFromRole(string application,string userName, string
roleName);
//更加多成员
}

View Code

  (四) IPasswordManager

添加UpdateCustomer视图

  那一个IPasswordManager接口首要提供与应用程序口令策略相关的只读音讯。

统计 10统计 11

[WebServiceBinding(“IPasswordManager”)]
interface IPasswordManager{
[WebMethod(…)]
bool EnablePasswordReset(string application);
[WebMethod(…)]
bool EnablePasswordRetrieval(string application);
[WebMethod(…)]
string GeneratePassword(string application,int length,
int numberOfNonAlphanumericCharacters);
[WebMethod(…)]
bool RequiresQuestionAndAnswer(string application);
[WebMethod(…)]
string ResetPassword(string application,string userName);
[WebMethod(…)]
string GetPassword(string application,string userName,string
passwordAnswer);
[WebMethod(…)]
void ChangePassword(string application,string userName,string
newPassword);
//更多成员
}

@model Core.Customer.CustomerInfo
@using ProjectBase.Utils
@Html.Raw(ViewBag.Msg)
<div class="areabx clear">
@*    <div class="areabx_header">@ViewBag.Title</div>*@
    <div class="tian_xi">
        @using (Html.BeginForm("UpdateCustomer", "Customer", FormMethod.Post, new { @clase = "form-inline", @role = "form", name = "from1" }))
        {
            <table width="100%" border="0" cellpadding="0" cellspacing="0">
                <tbody>
                    <tr style="height: 40px;">
                        <td style="width: 120px; text-align: right;">客户代码:</td>
                        <td>
                            @Html.TextBoxFor(x => x.CusCode, new { @class = "trade-timen", @id = "cusCode", @readOnly = "readOnly" })* @Html.ValidationMessageFor(m => m.CusCode)</td>
                        @Html.HiddenFor(x => x.ID)
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">客户名称:</td>
                        <td>
                            @Html.TextBoxFor(x => x.CusName, new { @class = "trade-timen", @id = "cusName" })* @Html.ValidationMessageFor(m => m.CusName)</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">手机:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Phone, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">电话:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Tel, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">邮箱:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Email, new { @class = "trade-timen", @id = "email" }) @Html.ValidationMessageFor(m => m.Email)</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">传真:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Fax, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">国家:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Country, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">地址:</td>
                        <td>
                            @Html.TextBoxFor(x => x.Address, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">公司名称:</td>
                        <td>
                            @Html.TextBoxFor(x => x.CompanyName, new { @class = "trade-timen" })</td>
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">业务类型:</td>
                        <td>
                        @Html.DropDownListFor(x => x.BusssinessType, @Html.EnumToList(typeof(Core.Customer.Busssiness), false), new { @class = "trade-timen", style = "width:180px" })
                    </tr>
                    <tr style="height: 40px;">
                        <td align="right">是否启用:</td>
                        <td>是 @Html.RadioButtonFor(x => x.Status, "0", new { Checked = "checked", @name = "status" }) &nbsp;&nbsp;&nbsp;&nbsp;
                            否 @Html.RadioButtonFor(x => x.Status, "1", new { @name = "status" })</td>
                    </tr>
                </tbody>
            </table>
            <input type="submit" value="确定" class="popbtn1 mg">
            <input type="button" value="关闭" class="popbtn3 mg2" onclick="frameElement.api.opener.updateDG.close();" />
        }
    </div>
</div>

  典型地,该策略存款和储蓄在应用程序的配备文件中。该方针包罗是或不是运营口令重置和寻找,口令强度和口令回答策略等。你也得以应用
IpasswordManager来生成一应和于该口令强度策略的新口令。此外,IpasswordManager可用于重置、改变或探寻一内定用户的口令。

View Code

  (五) IUserManager

客户实体CustomerInfo

  IUserManager接口允许校验用户凭证,检索剧中人物身份以及获得钦定用户是其成员之一的装有剧中人物。该接口用于测试和剖析指标。

统计 12统计 13

[WebServiceBinding(“IUserManager”)]
public interface IUserManager{
[WebMethod(…)]
bool Authenticate(string applicationName,string userName, string
password);
[WebMethod(…)]
bool IsInRole(string applicationName,string userName, string role);
[WebMethod(…)]
string[] GetRoles(string applicationName,string userName);
}
二、AspNetSqlProviderService Web服务

    /// <summary>
    /// 客户信息
    /// </summary>
    public class CustomerInfo //: DomainObject<CustomerInfo, int, ICustomerInfoRepository>
    {
        #region property
        /// <summary>
        /// 客户代码
        /// </summary>
        [Required(ErrorMessage = "客户代码不能为空!")]
        [StringLength(30, MinimumLength = 0, ErrorMessage = "客户代码最大长度为30个字符")]
        public virtual string CusCode { get; set; }
        /// <summary>
        /// 客户名称
        /// </summary>
        [Required(ErrorMessage = "客户名称不能为空!")]
        [StringLength(30, MinimumLength = 0, ErrorMessage = "客户名称最大长度为30个字符")]
        public virtual string CusName { get; set; }
        /// <summary>
        /// 客户业务类型
        /// </summary>
        public virtual Busssiness BusssinessType { get; set; }
        /// <summary>
        /// 手机
        /// </summary>
        public virtual string Phone { get; set; }
        /// <summary>
        /// 电话
        /// </summary>
        public virtual string Tel { get; set; }
        /// <summary>
        /// 邮箱
        /// </summary>
        [RegularExpression(@"^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$", ErrorMessage="邮箱格式不正确!")]
        public virtual string Email { get; set; }
        /// <summary>
        /// 传真
        /// </summary>
        public virtual string Fax { get; set; }
        /// <summary>
        /// 国家
        /// </summary>
        public virtual string Country { get; set; }
        /// <summary>
        /// 地址
        /// </summary>
        public virtual string Address { get; set; }
        /// <summary>
        /// 公司名称
        /// </summary>
        public virtual string CompanyName { get; set; }
        /// <summary>
        /// 金额
        /// </summary>
        public virtual decimal Balance { get; set; }
        /// <summary>
        /// 信用额度
        /// </summary>
        public virtual decimal CreditAmount { get; set; }
        /// <summary>
        /// 状态
        /// </summary>
        public virtual CustomerStatus Status { get; set; }
        /// <summary>
        /// 快件收货商信息
        /// </summary>
        public virtual IList<ExpressCurInfo> ExpressCurInfoBy { get; set; }
        #endregion

        #region common method
        /// <summary>
        /// 分页获取数据
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        public static IPageOfList<CustomerInfo> GetByFilter(CustomerFilter filter)
        {
            return Dao.GetByFilter(filter);
        }
        #endregion
    }

  呈现在所附源码中的列表4中的
AspNetSqlProviderService类达成了八个Web接口。其进程就象完毕任何别的接口一样-你能够隐式或显式地派生并达成格局(见列表
4)。作者是经过把那一个完结简单地代理到提供者的至极的方法来贯彻该Web接口上的绝当先3/6格局的。在每壹次接纳角色或地方此前,你必须为之作好准备-通过设置要利用的应用程序名。例如,为了兑现IRoleManager.CreateRole(),你将急需建立:

View Code

void IRoleManager.CreateRole(string application,string role){
Roles.ApplicationName = application;
Roles.CreateRole(role);
}

查询类CustomerFilter

  在那之中的一些宗目的在于调用该提供者前后还供给一点行事。例如,借使开发银行口令检索,你不得不寻找用户口令,而AspNetSqlProviderService则用于判定它。

统计 14统计 15

string IPasswordManager.GetPassword(string application,string
userName,
string passwordAnswer){
Membership.ApplicationName = application;
Debug.Assert(Membership.EnablePasswordRetrieval);
MembershipUser membershipUser =Membership.GetUser(userName);
return membershipUser.GetPassword(passwordAnswer);
}

    public class CustomerFilter : ParameterFilter
    {
        /// <summary>
        /// 客户代码
        /// </summary>
        public virtual string CusCode { get; set; }
        /// <summary>
        /// 客户名称
        /// </summary>
        public virtual string CusName { get; set; }

        /// <summary>
        /// 生产NHQL查询语句
        /// </summary>
        /// <returns></returns>
        public override string ToHql()
        {
            string hql = "";
            if (!string.IsNullOrEmpty(CusCode))
            {
                hql += " and Cus_Code =:CusCode ";
            }
            if (!string.IsNullOrEmpty(CusName))
            {
                hql += " and Cus_Name =:CusName ";
            }

            return hql;
        }

        /// <summary>
        /// 构造查询参数
        /// </summary>
        /// <returns></returns>
        public override Dictionary<string, object> GetParameters()
        {
            var result = new Dictionary<string, object>();
            if (!string.IsNullOrEmpty(CusCode))
            {
                result["CusCode"] = CusCode.Trim();
            }
            if (!string.IsNullOrEmpty(CusName))
            {
                result["CusName"] = CusName.Trim();
            }
            return result;
        }
    }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ProjectBase.Utils.Entities;

namespace ProjectBase.Data
{
    public abstract class ParameterFilter
    {
        public ParameterFilter()
        {
            HasQueryString = false;
            PageSize = 10;
        }

        public string OrderBy { get;set; }

        public abstract string ToHql();

        public override string ToString()
        {
            return ToHql();
        }

        public abstract Dictionary<string, object> GetParameters();

        public string GetOrderString()
        {
            if (OrderBy.HasValue())
                return " Order By " + OrderBy;
            return String.Empty;
        }

        protected string GetLike(string value)
        {
            return "%" + value + "%";
        }

        public int PageIndex { get; set; }

        public int PageSize { get; set; }

        /// <summary>
        /// 标识此构造器是包含全部查询语句。
        /// 若为 False,则ToHql() 只需要构造条件查询,系统会自动在前面加上<code>" from " + typeof(T).Name + " a where 1=1 "</code>
        /// 若为 True, ToHql() 需要返回 连form在类的完整Hql语句
        /// </summary>
        public bool HasQueryString { get; set; }

        protected static bool HasValue(string str)
        {
            return str.HasValue();
        }

        public static bool HasValue<T>(System.Nullable<T> value) where T:struct
        {
            return value.HasValue;
        }       

    }
}

  不过,还有一对办法并不曾获得提供者的直接帮衬。有二种恐怕的化解办法-第三种是尝尝并行使提供者的其它措施来成功所愿意的操作。第壹种是一贯实施
aspnetdb数据库。二种格局都存在利弊。例如,能够设想达成MembershipManager.DeleteAllUsers()方法。你能够对该应用程序中的每一个用户调用身份提供者的DeleteUser()方法,如列表4所示。首先你要调用
IMembershipManager.GetAllUsers()方法来赢得应用程序中的全数用户。那正是你通过兑现该接口的类来利用该接口方法的显式完结方式。然后,你能够定义一个匿名方式来删除用户,把该匿名格局赋值到3个Action<string>代理,并且利用Array类的静态方法
ForEach<T>()删除每一个用户。

View Code

public delegate void Action<T>(T obj);
public abstract class Array : …
{
public static void ForEach<T>(T[] array,Action<T> action);
}

在那边,笔者只演示了控制器和视图的互动,至于Hhibernate和Unity等数据的操作,那里临时不讲,因为你也足以运用别的的O奥迪Q7M框架和IOC框架,诸如EF、AutoFac等等。那里根本教师jquery
datatables和ASP.NET
MVC的组合使用,可是此间只演示了客户端分页排序,前面笔者会讲服务器分页排序。笔者发觉,网上都不曾ASP.NET
MVC和Datatables结合的总体的服务器分页、排序的德姆o,只见到PHP的。于是本身不住的尝尝,三千越甲可吞吴,终于试验成功了,后边作者会为我们讲述落成方式。

  第②种办法的长处是其他与删除1个用户相关的里边活动(如也删除全部的剧中人物身份)依旧被执行。其不足是,你要求对该数据库做越多的调用。

  正如刚刚提到的,第二种格局是直接对aspnetdb数据库编制程序。当提供者没有提供其他方法来成功此职责时,那是最得力的。例如,提供者并不支持删除一应用程序,更不说删除全部的应用程序了。尽管你能够编写1个储存进度来做那件业务,但本身的另2个指标是不选择aspnetdb,而是采纳原始SQL命令来贯彻IApplicationManager.DeleteApplication()和
IApplicationManager.DeleteAllApplications()。作者已用一个AspNetDbTablesAdapter助理类(在此并未显示)包装了那么些命令。直接待上访问数据库的优点是您仅执行二个下令;不足之处是,要是要转移数据库情势,你将索要转移你的代码。假定如删减全体的用户或一应用程序等操作是相似不涉及的还要一级用户的多寡常常不大,那么自个儿想最好尽也许让AspNetSqlProviderService使用
ASP.NET 2.0提供者。

  (一) 设置服务

  由AspNetSqlProviderServiceWeb服务使用的Web.Config文件中的设置影响它管理的具有应用程序。尤其地,如口令策略那样的安装适用于全数的应用程序。该服务使用默许提供者
(SQL
SERAV4VE科雷傲),由此只要缺省的接连字符串(在文件machine.config中珍贵)已经丰盛的话,就不需求内定1个提供者甚至3个连连字符串。如果你须要叁个不比的连日字符串,你须要包罗一个connectionStrings标签(见所附源码中的列表5)。别的,为了利用Roles类,你无法不透过下列指令来运维基于角色的安全。

<roleManager enabled=”true” />

  (二) 敬服服务

  固然其证据由AspNetSqlProviderServiceWeb服务来管理的应用程序可能是根据互连网或根据内部网的,可是服务本人是被规划由一个管理员通过地点内部网来存取的。你应当表明和授权到该服务的调用。别的,你还应当经过加密通信来提供隐衷服务。那是要求的,因为该服务要处理如用户名和口令等趁机音信。保证机密的最不难的办法是选取HTTPS。
AspNetSqlProviderService在它的构造器中路过静态VerifySecureConnection()助理方法来展开求证是或不是采纳了多少个康宁连接。VerifySecureConnection()使用当前伏乞的IsSecureConnection属性。为了支持支付或该服务的此外品类的非生产性发布,VerifySecureConnection()方法用Conditional属性加以修饰。唯有定义编写翻译符号HTTPS时该措施展才能会起效果。关于认证该服务的用户,既然Web服务是一地面内部网服务,那么使用Windows认证就不会有其它不当了。笔者接纳了采用集成的
Windows认证-那将节省了用户必须旗帜显然地登录的辛劳。集成的评释的此外一个优点是,它用一种专利格局来散列化发送过去的凭证。

  为了安顿集成的Windows认证,转到在IIS下的AspNetSqlProviderServiceWeb服务属性,选拔目录安全选项卡,并且点击”艾德it…”按钮。不选取”Anonymous
access”复选框并且保障选中”Integrated Windows
authentication”复选框。AspNetSqlProviderService类被安插以须求验证(见列表4)-它利用
PrincipalPermission属性并把被认证的属性设计为true。

[PrincipalPermission(SecurityAction.Demand,…,Authenticated=true)]

  一旦调用者通过IIS被表明,该服务缺省级地区级将在IIS中以布署的身价照旧运维。小编想以调用者身份运转该服务。为此,Web.Config文件(见列表5)蕴含了多个identity标签-它把impersonate属性设置为true。

<identity impersonate=”true”/>

  然后,你供给动用SQL
SE奥迪Q7VE哈弗管理工科具来允许Web服务的调用者从aspnetdb数据库中展开读和写。

  体贴该Web服务的另三个主要地点是授权。我想要验证唯有Windows一级用户组的积极分子才能存取这一劳务。为此,AspNetSqlProviderService类上的PrincipalPermission属性必要唯有一级用户剧中人物的分子才被允许利用该服务。

[PrincipalPermission(SecurityAction.Demand,
Role = “Administrators”,…)]

  你能够用别样其余组(该服务的莫过于用户应该是里面包车型大巴一员)来替换”Administrators”。

  PrincipalPermission属性使用配属于该线程的攀枝花官员(principal)来表达调用者是或不是真的是点名剧中人物中的一员。在依靠于NT组(如一级用户)时,那将挟持你利用多个WindowsPrincipal的实例。

public class WindowsPrincipal : IPrincipal{
 public WindowsPrincipal(WindowsIdentity ntIdentity);
 public virtual bool IsInRole(string role);
 //别的成员部分
}

  难题在于,为了利用Roles类,AspNetSqlProviderServiceWeb.Config文件必须运行基于剧中人物的安全策略。

<roleManager enabled=”true” />

  那反过来使得ASP.NET
2.0把一不等的principal依附到HttpContext和线程上,当然还有RolePrincipal类。

public sealed class RolePrincipal : IPrincipal{…}

  在NT超级用户剧中人物中间试验图使用RolePrincipal和矫枉过正要求的身价将会破产,因为它将存取aspnetdb而不是Windows组来寻找它。为补充那一点,你必须手工业地调换那些管事人同时在历次请求时把WindowsPrincipal的叁个实例依附到该线程上。为此,最简单的艺术是把一个Global.asax文件添加到该Web服务工程-通过点名在Global.cs文件中的Global类为类后的代码。

<%@ Application Language=”C#” CodeBehind =”Global.cs” Inherits =
“Global”%>

  这几个Global类为应用程序授权请求提供二个电脑。

public class Global : HttpApplication{
 protected void Application_AuthorizeRequest(object sender, EventArgs
e){
  if(HttpContext.Current.User.Identity.IsAuthenticated){
   WindowsIdentity identity = HttpContext.Current.User.Identity as
WindowsIdentity;
   Debug.Assert(identity != null);
   WindowsPrincipal principal;
   principal = new WindowsPrincipal(identity);
   Thread.CurrentPrincipal = principal;
  }
 } 
}

  借使调用者被证实,那么您供给实例化一新的WindowsPrincipal对象并且把它依附于近日线程。WindowsPrincipal构造器须求一个WindowsIdentity的实例。万幸,因为该服务正在使用Windows集成的表达,在成功验证后,与眼下HTTP上下文相关联的身价已经是
WindowsIdentity类型了,由此你能够只收获那几个实例。
**③ 、凭证管理器应用程序

**  本文相应的源代码包括了那个证据管理器应用程序-3个具备充裕的用户接口的Windows表单应用程序,它采纳在上一步描述的Web服务接口来为别的数据的应用程序管理安全凭证存款和储蓄。

  该应用程序导入八个Web接口定义,并且它独占地使用那几个接口。该应用程序有一个称作AspNetSqlProviderService的Web服务代办类-它用来固定该服务。你要求从导入的接口手工业地把它添加到该服务上。

统计 16
图4.Applications选项卡:这一个选项卡让你挑选要布局的应用程序。

partial class AspNetSqlProviderService :
SoapHttpClientProtocol,IMembershipManager,
IUserManager,IPasswordManager,
IApplicationManager,IRoleManager
{
 public AspNetSqlProviderService (){
  Credentials = CredentialCache.DefaultCredentials;
  Url = Settings.Default.AspNetSqlProviderService ;
 }
 //其余的实践
}

  为了帮衬集成的Windows认证,那几个代理类的构造器使用CredentialCache的静态属性DefaultCredentials设置凭证属性-它只是简短地读取当前线程的安全标志。此外,那一个构造器还选拔设计器生成的Settings类从应用程序配置类中读取Web服务地点。

统计 17
图5.Users选项卡:该选项卡列出在选定的应用程序中的全数用户。

  这一个应用程序的施用十一分直观,所以作者只介绍一下根本显示屏和甄选。Applications选项卡(见图4)允许你挑选要安排的应用程序。

  在此,选择一应用程序将震慑全数其余的选项卡。你能够创设和删除多少个应用程序或删除全部应用程序。Users选项卡列举出在甄选的应用程序中的全体用户。

  你能够创制或删除一用户。假如您剔除一用户但是不选拔”All
Data”复选框的话,它将去除该用户可是保持它的剧中人物身份消息。你能够更新一用户帐户或删除全部用户。根据从
AspNetSqlProviderServiceWeb服务再次来到的口令策略的例外,你能够或不能转移或重置口令,而且能够或不得以要求应对该口令。在Users选项卡的按钮和它所展现的对话框也相应地运维或取缔。

  在Users选项卡的出手是总结新闻,如当前用户的在线数。Roles选项卡允许你把剧中人物添加到应用程序。

统计 18
图6:Roles选项卡:那么些选项卡让你把角色添加到应用程序。

  当删除八个剧中人物时,要是你选拔了”Fail if
populated”复选框,那么只要它有其余成员来说,就不会让你删掉该角色。左侧的列表视图呈现在该应用程序中的全体用户。你能够从1个剧中人物添加或删除一用户,或从具有剧中人物中去除一用户。在底部,”Users
in role”列表框展现了在上边选定的剧中人物中的全部用户,而”Roles for
User”列表框展现了在上头选定的用户中的全体剧中人物。

  Passwords选项卡呈现在图7中,它列出已安排的口令策略并且同意你生成一与钦命的口令强度策略相匹配的新口令。

统计 19
图7.Passwords选项卡:你能够动用那么些选项卡生成一口令。

统计 20
图8.Credentials Service选项卡:使用那几个选项卡来选取选用的Web服务。

  该选项卡让您选拔要利用的Web服务。一旦运维,凭证管理器应用程序即从应用程序配置文件中读取那么些地方。这几个选项卡展现被挑选的Web服务。假设地方是于事无补的,也正是说,该服务不支持具备要求的意义,那么在应用程序中的全数控件都将为空且是禁止的。你能够提供3个不等的地址,而上面包车型客车Web浏览器控件将会突显这一劳务。然则,若是该服务支撑须求的Web方法(一立见成效的Web服务)的话,你能够只选拔三个Web服务地点(通过点击Select按钮)。若是该服务是不著见效的,那么将禁止Select按钮。

  不幸的是,在.NET
2.0中没有提供销商业高校验某服务是还是不是协理一特意绑定或Web接口的停放协理,因此小编只可以手工业完结。所附源码中的列表6来得出
RefreshSelectButton()和ContainsInterface()助理方法。RefreshSelectButton()首先禁止
Select按钮和相匹配的菜单项。然后,验证内定的地方是一个.NET
Web服务的地点。然后,它存取显示在Web浏览器控件中的页面的剧情还要认证它含有帮助具有的接口的措施。为此,它要调用
ContainsInterface()方法并把页面包车型客车内容和要证实的接口类型提要求它。ContainsInterface()验证该项目是一个接口的类别并且赢得三个MethodInfo对象数组-标记在该接口上的各类方法。然后,它定义3个吸收单个实例MethodInfo的匿名格局并且应用字符串类的Contains()方法来验证该内容包涵那么些情势。ContainsInterface()使用该数组类的静态TrueForAll<T>()方法。

public delegate bool Predicate<T>(T obj);
public abstract class Array : …
{
 public static bool TrueForAll<
 T>(T[] array,Predicate<
 T> match);
}

  ContainsInterface()提供给TrueForAll()贰个MethodInfo对象数组和匿名方式格局的Predicate。唯有在该内容中找到全部的法羊时,TrueForAll<T>()才回来true。
http://www.7dspace.com/doc/24/0512/2005123006395536935_1.htm