我有一个名为Property的内容类型,它是在Orchard管理员Web界面中创建的。属性包含多个字段,其中2个是地址和价格。
我创建了一个查询过滤属性内容类型,并希望通过Projection根据URL查询字符串参数对这些内容进行排序。例如。 〜/ PropertyProjection?sortfield = price& sortasc = true 会按价格升序对属性进行排序。
下面的代码用于分类价格,但我想知道是否有更好,更简单,更有效的方法来实现这一目标。特别是我想自动设置propertyName和dataType变量。
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.MetaData;
using Orchard.Localization;
using Orchard.Projections.Descriptors.SortCriterion;
using Orchard.Projections.FieldTypeEditors;
using Orchard.Projections.Services;
using Orchard.Utility.Extensions;
namespace CustomModule.Providers {
public class PropertySortCriterionProvider : ISortCriterionProvider {
private readonly IContentDefinitionManager _contentDefinitionManager;
private readonly IEnumerable<IContentFieldDriver> _contentFieldDrivers;
private readonly IEnumerable<IFieldTypeEditor> _fieldTypeEditors;
private readonly IWorkContextAccessor _workContextAccessor;
public PropertySortCriterionProvider(
IContentDefinitionManager contentDefinitionManager,
IEnumerable<IContentFieldDriver> contentFieldDrivers,
IEnumerable<IFieldTypeEditor> fieldTypeEditors,
IWorkContextAccessor workContextAccessor)
{
_contentDefinitionManager = contentDefinitionManager;
_contentFieldDrivers = contentFieldDrivers;
_fieldTypeEditors = fieldTypeEditors;
_workContextAccessor = workContextAccessor;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public void Describe(DescribeSortCriterionContext describe) {
var descriptor = describe.For("Custom Property", T("Custom Property"), T("Custom Property sorts"));
descriptor.Element("PropertySortQueryParam", T("PropertySortQueryParam"),
T("Sort Property by the HTTP Query Sort parameters"),
context => ApplyFilter(context),
context => DisplaySortCriterion(context)
);
}
public void ApplyFilter(SortCriterionContext context)
{
//bool ascending = Convert.ToBoolean(context.State.Sort);
var sortField = _workContextAccessor.GetContext().HttpContext.Request.Params["sortfield"];
var ascending = true;
if (!bool.TryParse(_workContextAccessor.GetContext().HttpContext.Request.Params["sortasc"], out ascending))
ascending = true;
if (!string.IsNullOrEmpty(sortField)) {
var propertyName = "";
Type dataType = null;
var fieldName = "";
if (sortField.ToLower() == "price") {
propertyName = "Property.Price.";
dataType = typeof (Decimal);
fieldName = "Price";
}
//if we have valid sort criteria from the URL param
if (dataType != null) {
IFieldTypeEditor fieldTypeEditor = _fieldTypeEditors.FirstOrDefault(x => x.CanHandle(dataType));
var part = _contentDefinitionManager.ListPartDefinitions().First(p => p.Name == "Property");
var field = part.Fields.Where(f => f.Name == fieldName);
// use an alias with the join so that two filters on the same Field Type wont collide
var relationship = fieldTypeEditor.GetFilterRelationship(propertyName.ToSafeName());
// generate the predicate based on the editor which has been used
Action<IHqlExpressionFactory> predicate = y => y.Eq("PropertyName", propertyName);
// combines the predicate with a filter on the specific property name of the storage, as implemented in FieldIndexService
// apply where clause
context.Query = context.Query.Where(relationship, predicate);
// apply sort
context.Query = ascending
? context.Query.OrderBy(relationship, x => x.Asc("Value"))
: context.Query.OrderBy(relationship, x => x.Desc("Value"));
}
}
}
public LocalizedString DisplaySortCriterion(SortCriterionContext context) {
bool ascending = Convert.ToBoolean(context.State.Sort);
if (ascending) {
return T("Ordered by Custom Property HTTP Query Sort parameters ascending");
}
return T("Ordered by Custom property HTTP Query Sort parameters descending");
}
}
}
以上代码基于Orchard.Projections.Providers.SortCriteria中的ContentFieldsSortCriterion
请在答案中提供代码示例。
干杯,
安德鲁
答案 0 :(得分:0)
这是一个查询排序提供程序,它允许对HTTP请求查询参数中指定的任何字段进行排序。
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.MetaData;
using Orchard.Localization;
using Orchard.Projections.Descriptors.SortCriterion;
using Orchard.Projections.FieldTypeEditors;
using Orchard.Projections.Services;
using Orchard.Utility.Extensions;
using Orchard.Events;
using Orchard.Environment.Extensions;
using Orchard.ContentManagement.Handlers;
namespace CustomModule.Providers.SortCriteria {
public class QueryParamSortCriterionProvider : ISortCriterionProvider {
private readonly IContentDefinitionManager _contentDefinitionManager;
private readonly IEnumerable<IContentFieldDriver> _contentFieldDrivers;
private readonly IEnumerable<IFieldTypeEditor> _fieldTypeEditors;
private readonly IWorkContextAccessor _workContextAccessor;
public QueryParamSortCriterionProvider(
IContentDefinitionManager contentDefinitionManager,
IEnumerable<IContentFieldDriver> contentFieldDrivers,
IEnumerable<IFieldTypeEditor> fieldTypeEditors,
IWorkContextAccessor workContextAccessor)
{
_contentDefinitionManager = contentDefinitionManager;
_contentFieldDrivers = contentFieldDrivers;
_fieldTypeEditors = fieldTypeEditors;
_workContextAccessor = workContextAccessor;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public void Describe(DescribeSortCriterionContext describe) {
var descriptor = describe.For("General", T("General"), T("General sort criteria"));
descriptor.Element("QueryParamField", T("Query Param Field"),
T("Sorts results using query parameters on the HTTP request"),
context => ApplyFilter(context),
context => DisplaySortCriterion(context)
);
}
public void ApplyFilter(SortCriterionContext context)
{
var sortField = _workContextAccessor.GetContext().HttpContext.Request.Params["sortby"];
if (string.IsNullOrWhiteSpace(sortField)) {
return;
}
var ascending = true;
if (!bool.TryParse(_workContextAccessor.GetContext().HttpContext.Request.Params["sortasc"], out ascending))
ascending = true;
var sortFieldElements = sortField.Split(new []{'.'}, 2);
if (sortFieldElements.Length != 2) {
return;
}
var part = _contentDefinitionManager.ListPartDefinitions().FirstOrDefault(p => p.Name == sortFieldElements[0]);
if (part == null) {
return;
}
var field = part.Fields.FirstOrDefault(f => f.Name == sortFieldElements[1]);
if (field == null) {
return;
}
var drivers = _contentFieldDrivers.Where(x => x.GetFieldInfo().Any(fi => fi.FieldTypeName == field.FieldDefinition.Name)).ToList();
var membersContext = new DescribeMembersContext(
(storageName, storageType, displayName, description) => {
// look for a compatible field type editor
IFieldTypeEditor fieldTypeEditor = _fieldTypeEditors.FirstOrDefault(x => x.CanHandle(storageType));
if (fieldTypeEditor != null) {
var propertyName = String.Join(".", part.Name, field.Name, storageName ?? "");
// use an alias with the join so that two filters on the same Field Type wont collide
var relationship = fieldTypeEditor.GetFilterRelationship(propertyName.ToSafeName());
// generate the predicate based on the editor which has been used
Action<IHqlExpressionFactory> predicate = y => y.Eq("PropertyName", propertyName);
// combines the predicate with a filter on the specific property name of the storage, as implemented in FieldIndexService
// apply where clause
context.Query = context.Query.Where(relationship, predicate);
// apply sort
context.Query = ascending
? context.Query.OrderBy(relationship, x => x.Asc("Value"))
: context.Query.OrderBy(relationship, x => x.Desc("Value"));
}
});
foreach (var driver in drivers) {
driver.Describe(membersContext);
}
}
public LocalizedString DisplaySortCriterion(SortCriterionContext context) {
return T("Ordered by fields specified by HTTP query parameters (eg. ?sortby=PartName.FieldName&sortasc=true)");
}
}
}