使用 ASP.NET MVC 2 时保留过滤选项的更好方法的指南 [英] Guidance on a better way to retain filtering options when using ASP.NET MVC 2

查看:8
本文介绍了使用 ASP.NET MVC 2 时保留过滤选项的更好方法的指南的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 ASP.NET MVC 2 应用程序,它部分允许用户过滤数据并在 JQGrid 中查看该数据.

目前这包括一个控制器,它初始化我的过滤器模型并配置我希望我的网格如何显示.视图和局部视图使用此信息来显示过滤器和网格外壳.我使用编辑器模板来显示我的过滤器.JQGrid 使用 JsonResult 控制器操作 (GET) 来检索过滤器的结果(添加网格提供的分页 - GET 请求仅返回一页数据.网格使用的 Uri请求数据包含过滤器模型作为 RouteValue - 当前包含过滤器当前状态的字符串表示形式.自定义 IModelBinder 用于将此表示形式转换回过滤器模型类的实例.

用户可以更改过滤器并按下提交按钮以获得不同的结果 - 然后由 (HttpPost) ViewResult 操作获取过滤器模型 - 由进一步的模型绑定器重构并导致网格外壳更新了.

所以我有:

过滤器模型代表用户想要的过滤特性

FilterModelEditorTemplateSubmissionBinder : DefaultModelBinder - 用于将用户提供的更改过滤特性的请求信息转换为适当的 FilterModel 实例.

FilterModelStringRepresentationBinder : IModelBinder - 用于从 JQGrid GET 数据请求转换编码过滤器,以便对最终执行查询并返回相关数据的服务发出正确的请求.p>

ViewResult Index() - 构造默认过滤器,配置网格规范并返回视图以呈现过滤器的编辑器模板和网格外壳.

[HttpPost]ViewResult Filter(FilterModel filter) - 采用新的过滤器特征并返回与 Index() 相同的视图.使用 FilterModelEditorTemplateSubmissionBinder 绑定过滤器模型.

JsonResult GetData(FilterModel filter, string sidx, string sord, int page, int rows) - 从 JQGrid 调用以检索数据.使用 FilterModelStringRepresentationBinder 绑定过滤器模型.

作为一个复杂因素,我的过滤器模型包含一个从项目集合中选择单个值的选项.此集合是从服务请求中检索的,我不想每次显示过滤器时都继续查询此数据,目前如果属性为空,我会得到它,然后将隐藏在编辑器模板中的选项和编码包含在字符串表示.然后这些选项由相关的模型绑定器重新构成.

虽然这种方法有效,但我不禁觉得我必须从根本上重新发明视图状态才能维护我的过滤器和包含的选项.由于我是 ASP.NET MVC 的新手,但对经典的 ASP 和 ASP.NET Web 窗体非常满意,所以我想我会把它扔在那里征求意见和指导,以找到一种更符合 MVC 模式的方法.

解决方案

在我看来,最好的方法是将一些为 jqGrid 提供纯数据的操作与其他控制器操作分开.这种面向 jqGrid 的动作可以有如下原型:

JsonResult GetData(string filter, string sidx, string sord, int page, int rows)

我个人更喜欢将此部分实现为 WCF 服务,并将此 WCF 服务作为同一个 ASP.NET 站点的一部分.一般来说,这更多的是品味问题,取决于您的其他项目要求.

ASP.NET 站点的这一部分可以实现您需要的用户身份验证,并且可以像控制器的其他操作一样使用单元测试进行测试.

ASP.NET MVC 站点的视图可以有 空数据 用于 jqGrids,并且只有正确的 URL,并且可能生成 HTML 代码取决于站点中的用户权限.每个页面将根据对服务器的相应请求填充 jqGrids 的数据(对相应 GetData 操作的请求).

您可以对数据使用 HTTP GET 以获得最佳数据缓存.数据的缓存是单独讨论的主题.如果你这样做了,你应该在 jqGrid 的定义中使用 prmNames: { nd:null } 来移除唯一的 nd 参数,并默认为每个 GET 请求添加时间戳.要完全控制服务器端的数据缓存,您可以添加服务器响应的 HTTP 标头,将 "Cache-Control" 设置为 "max-age=0""ETag" 标头,其值根据响应中返回的数据计算得出.您应该测试来自客户端的请求是否具有 "If-None-Match" 值为 "ETag" 的 HTTP 标头与缓存在客户端上的数据相对应.然后你应该验证服务器上的当前数据(在数据库中)是否改变了,如果没有改变,则生成一个带有 empty 正文的响应(设置 SuppressEntityBody为 true)并返回304 Not Modified"状态代码(HttpStatusCode.NotModified)而不是默认的200 OK".更详细的解释更长.

如果您不想优化站点以缓存 jqGrids 的 HTTP GET 数据,您可以使用 HTTP POST 或不使用 prmNames: { nd:null } 参数.

JsonResult GetData(string filter, string sidx, string sord, int page, int rows)里面的代码不是很缺原因.您应该从 filter 字符串反序列化 JSON 数据,然后根据您使用的数据访问方法(LINQ to SQL、实体模型或 SqlCommandSqlDataReader).因为你已经实现了这部分,所以讨论这部分没有意义.

我的建议的主要部分可能是使用明确分离控制器操作,为所有 jqGrids 提供数据,以及使用带有 empty 数据的 MVC 视图(只有 <table id="list"></table><div id="pager"></div>).毫无疑问,您应该有一个相对较长的代码来分析来自 jqGrid 的高级搜索功能并生成或对您的数据模型相应的请求的过滤器.只需执行一次.在我的实现中,代码也相对复杂,但它已经编写过一次,它可以工作并且可以用于所有新的 jqGrid.

I have an ASP.NET MVC 2 application which in part allows a user to filter data and view that data in a JQGrid.

Currently this consists of a controller which initialises my filter model and configures how I wish my grid to be displayed. This information is used by a view and a partial view to display the filter and the grid shell. I use an editor template to display my filter. The JQGrid makes use of a JsonResult controller action (GET) to retrieve the results of the filter (with the addition of the paging offered by the grid - only a single page of data is returned by the GET request. The Uri used by the grid to request data contains the filter model as a RouteValue - and currently contains a string representation of the current state of the filter. A custom IModelBinder is used to convert this representation back into an instance of the filter model class.

The user can change the filter and press a submit button to get different results - this is then picked up by an (HttpPost) ViewResult action which takes the filter model - reconstituted by a further model binder and causes the grid shell to be updated.

So I have:

FilterModel Represents the user's desired filtering characteristics

FilterModelEditorTemplateSubmissionBinder : DefaultModelBinder - used to convert the request information supplied from a user changing their filtering characteristics into the appropriate FilterModel instance.

FilterModelStringRepresentationBinder : IModelBinder - used to convert the encoded filter from the JQGrid GET request for data so the correct request is made of the service which is ultimately performing the query and returning the relevant data.

ViewResult Index() - constructs a default filter, configures the grid specification and returns the view to render the filter's editor template, and the grid shell.

[HttpPost]ViewResult Filter(FilterModel filter) - takes the new filter characteristics and returns the same view as Index(). Uses FilterModelEditorTemplateSubmissionBinder to bind the filter model.

JsonResult GetData(FilterModel filter, string sidx, string sord, int page, int rows) - called from the JQGrid in order to retrieve the data. Uses FilterModelStringRepresentationBinder to bind the filter model.

As a complication, my filter model contains a option to select a single value from a collection of items. This collection is retrieved from a service request and I don't want to keep querying for this data everytime I show the filter, currently I get it if the property is null, and then include the options hidden in the editor template and encoding in the string representation. These options are then reconstituted by the relevant model binder.

Although this approach works I can't help but feel that I am having to basically reinvent viewstate in order to maintain my filter and the included options. As I am new to ASP.NET MVC but am very happy with classic ASP and ASP.NET Web Forms I thought I'd throw this out there for comment and guidance as to find a way which more closely fits with the MVC pattern.

解决方案

It seems to me that the best way in to divide some actions which provide pure data for the jqGrid from other controller action. Such jqGrid-oriented actions can have prototype like:

JsonResult GetData(string filter, string sidx, string sord, int page, int rows)

I personally prefer to implement this part as WCF service and to have this WCF service as a part of the same ASP.NET site. In general it's much more the matter of taste and depends on your other project requirements.

This part of you ASP.NET site could implement users authentication which you need and can be tested with unit tests exactly like other actions of your controllers.

The views of the ASP.NET MVC site can have empty data for jqGrids, and have only correct URLs and probably generate the HTML code depends on the users permission in the site. Every page will fill the data of jqGrids with respect of the corresponds requests to the server (request to the corresponding GetData action).

You can use HTTP GET for the data for the best data caching. The caching of data is the subject of a separate discussion. If you do this, you should use prmNames: { nd:null } in the definition of jqGrid to remove unique nd parameter with the timestamp added per default to every GET request. To have full control of the data caching on the server side you can for example add in HTTP headers of the server responses both "Cache-Control" set to "max-age=0" and "ETag" header with the value calculated based of the data returned in the response. You should test whether the request from the client has "If-None-Match" HTTP header with the value of "ETag" coresponds the data cached on the client. Then you should verify whether the current data on the server (in the database) are changed and, if there are not changed, generate a response with an empty body (set SuppressEntityBody to true) and return "304 Not Modified" status code (HttpStatusCode.NotModified) instead of default "200 OK". A more detail explanation is much more longer.

If you don't want optimize you site for caching of HTTP GET data for jqGrids you can either use HTTP POST or don't use prmNames: { nd:null } parameter.

The code inside of JsonResult GetData(string filter, string sidx, string sord, int page, int rows) is not very short of cause. You should deserialise JSON data from the filter string and then construct the request to the data model depends on the method of the data access which you use (LINQ to SQL, Entity Model or SqlCommand with SqlDataReader). Because you have this part already implemented it has no sense to discuss this part.

Probably the main part of my suggestion is the usage of clear separation of controller actions which provide the data for all your jqGrids and the usage of MVC views with empty data (having only <table id="list"></table><div id="pager"></div>). You should also has no doubt with having a relative long code for analyzing of filters which come from the Advance Searching feature of the jqGrid and generating or the corresponding requests to your data model. Just implement it one time. In my implementation the code in also relatively complex, but it is already written one time, it works and it can be used for all new jqGrids.

这篇关于使用 ASP.NET MVC 2 时保留过滤选项的更好方法的指南的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆