如何处理 ASP.NET MVC 中的报告过滤器?

发布于 2024-07-10 21:17:26 字数 197 浏览 4 评论 0原文

对于给定的报告,用户将希望有多个过滤选项。 当选项是枚举和其他“静态”数据类型时,这还不错,但是当您需要一个由存储在后端表中的字段填充的选择列表时,事情可能会变得很愚蠢。

您如何处理这种情况? 我发现自己不断地重塑视图数据以适应额外的过滤器字段,但它确实开始有点过多地跟踪不仅选定的选项,而且跟踪选项本身......

有没有更好的方法?

For a given report, the user will want to have multiple filtering options. This isn't bad when the options are enumerations, and other 'static' data types, however things can get silly fast when you need a select list that is populated by fields stored in a table in the backend.

How do you handle this scenario? I find myself constantly reshaping the View data to accommodate the additional filter fields, but it really is starting to be a bit much tracking not only the selected options, but also the options themselves...

is there not a better way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

望喜 2024-07-17 21:17:26

我目前正在为我们工作中的一款产品构建一个新的报告部分,并正在处理同样的问题。 到目前为止,我提出的解决方案虽然尚未实施,但仍然是一项正在进行的工作,符合这一点。

将有一个类表示报告过滤器,其中包含一些基本信息,例如标签文本和选项值列表。

public enum DisplayStyle
{
    DropDown,
    ListBox,
    RadioList,
    CheckList,
    TextBox
}

public class FilterOption
{
    public string Name { get; set; }
    public string Value { get; set; }
    public bool Selected { get; set; }
}

public class ReportFilter
{
    public string Title { get; set; }
    public DisplayStyle Style { get; set; }
    public List<FilterOption> Options { get; set; }
}

然后我的模型将包含这些选项类的列表,这些选项类将根据每个报告的需求生成。 我还有一个基本报告类,每个报告都将从该类继承,这样我就可以在每个报告的基础上构建选项列表,并使用一个视图来处理所有选项列表。

public class ReportModel
{
    public string Name { get; set; }
    public List<ReportFilter> Filters { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
}

然后在我的视图中,我将有一些辅助方法,它们将接受这些选项类并为我构建实际的控件。

public static string ReportFilter(this HtmlHelper htmlHelper, DisplayStyle displayStyle, FilterOption filterOption)
{
    switch (displayStyle)
    {
        case DisplayStyle.TextBox:
            return string.Format("<input type=\"text\"{0}>", filterOption.Selected ? (" value=\"" + filterOption.Value + "\"") : string.Empty);
            break;
        ...
    }
}

我的路线看起来像这样

Reports/{reportID}/start/{startDate}/end/{endDate}/{*pathInfo}

所有报告都有开始和结束日期,然后是可选的过滤器。 catchall 参数将具有“Customer/1,4,7/Program/45,783”形式的过滤器值列表。 所以它就像列表形式的键/值对。 然后,当控制器加载时,它会将这些值解析为更有意义的内容。

public static Dictionary<string, string> RouteParams(string pathInfo)
{
    if (string.IsNullOrEmpty(pathInfo))
    {
        return new Dictionary<string, string>();
    }

    var values = new Dictionary<string, string>();

    // split out params and add to the dictionary object

    return values;
}

然后它将它们传递给报告类并验证它们以确保它们对于该报告是正确的。 然后,当为该报告加载选项时,URL 中设置的任何内容都将在 ReportOption 类中设置为 Selected,以便可以维护它们的状态。 然后过滤器列表和其他报告数据将添加到模型中。

对于我的设置,当另一个过滤器选择发生变化时,某些过滤器也会发生变化,因此这里会有一些 AJAX 来发布数据并获取更新的过滤器选项。 当您缩小搜索条件时,向下钻取的工作方式类似于亚马逊或新蛋上的搜索选项。

我希望这一切对我身边的人来说都是有意义的。 如果有人对改进它有一些意见,我很乐意听到。

I’m currently building out a new reporting section for one of our products at work and am dealing with this same issue. The solution I’ve come up with so far, though it hasn’t been implemented yet so this is still a work in progress, is along the lines of this.

There will be a class that will represent a report filter which will contain some basic info such as the label text and a list of option values.

public enum DisplayStyle
{
    DropDown,
    ListBox,
    RadioList,
    CheckList,
    TextBox
}

public class FilterOption
{
    public string Name { get; set; }
    public string Value { get; set; }
    public bool Selected { get; set; }
}

public class ReportFilter
{
    public string Title { get; set; }
    public DisplayStyle Style { get; set; }
    public List<FilterOption> Options { get; set; }
}

And then my model will contain a list of these option classes that will be generated based on each report’s needs. I also have a base report class that each report will inherit from so that way I can handle building out the option lists on a per report basis and use one view to handle them all.

public class ReportModel
{
    public string Name { get; set; }
    public List<ReportFilter> Filters { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
}

Then inside my view(s) I’ll have some helper methods that will take in those option classes and build out the actual controls for me.

public static string ReportFilter(this HtmlHelper htmlHelper, DisplayStyle displayStyle, FilterOption filterOption)
{
    switch (displayStyle)
    {
        case DisplayStyle.TextBox:
            return string.Format("<input type=\"text\"{0}>", filterOption.Selected ? (" value=\"" + filterOption.Value + "\"") : string.Empty);
            break;
        ...
    }
}

My route would look like this

Reports/{reportID}/start/{startDate}/end/{endDate}/{*pathInfo}

All reports have a start and end date and then optional filters. The catchall parameter will have lists of filter values in the form of “Customer/1,4,7/Program/45,783”. So it’ll be like a key/value pair in list form. Then when the controller loads it’ll parse out those values into something more meaningful.

public static Dictionary<string, string> RouteParams(string pathInfo)
{
    if (string.IsNullOrEmpty(pathInfo))
    {
        return new Dictionary<string, string>();
    }

    var values = new Dictionary<string, string>();

    // split out params and add to the dictionary object

    return values;
}

Then it will pass them off to the report class and validate them to make sure they’re correct for that report. Then when the options are loaded for that report anything that’s been set in the URL will be set to Selected in the ReportOption class so their state can be maintained. Then the filter list and other report data will be added to the model.

For my setup some filters will change when another filters selection changes so there will be some AJAX in here to post the data and get the updated filter options. The drilldown will work sort of like the search options at amazon or newegg when you narrow your search criteria.

I hope that all makes sense to someone beside me. And if anyone has some input on improving it I’d be happy to hear it.

青衫儰鉨ミ守葔 2024-07-17 21:17:26

您可以使用 MVC 应用程序中的 jQuery 和 JsonResults 在屏幕上异步检索数据,这就是我们在应用程序中填充所有列表和搜索的方式。 我在这里有一个如何完成的示例.

这样,视图数据就会按需加载,如果他们不使用额外的过滤器,那么他们就不必获取视图数据,并且如果一个选择与另一个选择相关,那么很清楚您要选择哪一组数据需要检索。

另一种选择,虽然我不太喜欢这个,但 jQuery 解决方案可能不适合你,是让你的视图的模型对象包含所有视图数据,这样你需要做的就是设置单个模型对象和所有列表是直接加载的并且是强类型的。 这将简化视图和后端代码,因为更清楚的是,对于此视图,您唯一需要的是此模型对象的完整版本。

例如,如果您有两个组合框列表,那么您的模型可能如下所示:

public class MyViewMode
{
    public int MyProperty { get; set; }
    public string SomeString { get; set; }
    List<string> ComboListA { get; set; }
    List<string> ComboListB { get; set; }
}

希望这是有道理的,如果没有,请发表评论,我将对其进行扩展。

You could go and retrieve the data asynchronously on the screen using jQuery and JsonResults from your MVC application, this is how we populate all of our lists and searches in our applications. I have an example of how it is done here.

This way the view data is loaded on demand, if they don't use the extra filters then they don't have to get the view data and if one selection relates to another then it's clear which set of data you need to retrieve.

Another option, though I don't like this one as much but jQuery solution may not suit you, is to have your model object for your view contain all the view data so that all you need to do is set the single model object and all the lists are loaded directly and strongly typed. This will simplify the view and the back end code because it will be more clear that for this view the only thing you need is a complete version of this model object.

For example if you had two lists for combo boxes then your model might look like:

public class MyViewMode
{
    public int MyProperty { get; set; }
    public string SomeString { get; set; }
    List<string> ComboListA { get; set; }
    List<string> ComboListB { get; set; }
}

Hope that makes sense, if not please comment and I'll expand on it.

李不 2024-07-17 21:17:26

对报告进行临时过滤确实是一个棘手的问题,特别是当您想要根据数据类型显示自定义用户界面控件、进行验证、使某些过滤器相互依赖而其他过滤器不依赖等时。

我认为一件事值得考虑的是这里古老的“构建与购买”问题。 有专门用于临时报告的工具,它们确实为临时过滤器提供了 UI,可以帮助解决此问题,例如常见的嫌疑人 水晶报告Microsoft 的 Reporting Services,或我们的产品 ActiveReports Server。 在 ActiveReports Server 中,我们支持级联提示(其中提示中的可用值相互依赖),并使任何人(甚至非技术业务用户)都可以轻松修改提示(假设他们显然具有权限)。 有关在 ActiveReports Server 中使用提示的更多信息位于此处。 ActiveReports Server 也是全部托管 .NET 代码,并提供 ASP.NET 控件和 Web 服务,允许您将其集成到 Web 应用程序中。

Scott Willeke
Product Manager - ActiveReports Server
GrapeCity inc.

Ad-hoc filtering on reports is indeed a tricky issue especially when you want to show a custom user interface control based on the data type, do validation, make some filters to be dependent on one another and others not, etc.

One thing I think that is worth considering is the old "build vs buy" issue here. There are specialized tools out there for ad-hoc reporting that do provide a UI for ad-hoc filters help with this such as the usual suspects Crystal Reports, Microsoft's Reporting Services, or our product ActiveReports Server. In ActiveReports Server we support cascading prompts (where available values in prompts depend on one another) and make it easy for anyone, even non-technical business users to modify the prompts (assuming they have permissions obviously). More information about using prompts in ActiveReports Server is here. ActiveReports Server is also, all managed .NET code, and provides ASP.NET controls and web services that allows you to integrate it into your web apps.

Scott Willeke
Product Manager - ActiveReports Server
GrapeCity inc.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文