какой шаблон разработки использовать для фильтрации запроса? c#

В основном @Html.ActionLink() помощник отображает тег привязки (<a>) с атрибутами и по умолчанию использует запрос GET, обновляя всю страницу, поэтому вам необходимо добавить preventDefault() для использования обратного вызова AJAX из этого элемента. Если в методе действия используется метод HTTP GET, вы можете выполнить простой вызов AJAX для общего класса якорной ссылки, например:

$('.text-info').on('click', function (e) {
    e.preventDefault();

    var url = $(this).attr('href');
    $.get(url, function (response) {
        // do something with AJAX response
    });
});

Однако, поскольку действие целевого контроллера помечено как [HttpPost], необходимо извлечь запрос строковые параметры из атрибута href с дополнительной функцией и использовать их в вызове AJAX с установкой type: 'POST', или использовать $.post():

$('.text-info').on('click', function (e) {
    e.preventDefault(); // mandatory to prevent GET request

    var url = $(this).attr('href');

    var pcs = getQueryStringParams(url, 'ProductCodeScheme');
    var pc = getQueryStringParams(url, 'ProductCode');
    var sn = getQueryStringParams(url, 'SerialNumber');
    var batch = getQueryStringParams(url, 'Batch');
    var expDate = getQueryStringParams(url, 'ExpirationDate');
    var csc = getQueryStringParams(url, 'CommandStatusCode');

    // create key-value pair for action method parameters
    var obj = { ProductCodeScheme: pcs, ProductCode: pc, SerialNumber: sn, ... }

    $.ajax({
        type: 'POST',
        url: url.split('?')[0], // URL without query string, or use '@Url.Action("VerifyPack", "Home")'
        data: obj,
        dataType: 'json', // expects response as JSON
        success: function (response) {
            // do something with AJAX response
        },
        error: function (xhr, status, err) {
            // error handling
        }
    });

    // just make sure that the link is not redirecting
    return false;
});

function getQueryStringParams(url, name) {
     return (RegExp(name + '=' + '(.+?)(&|$)').exec(url)||[,null])[1];
}

На самом деле существует другой способ вызова AJAX из тега привязки, например @Ajax.ActionLink(), в зависимости от вашего выбора:

@Ajax.ActionLink("Verify Pack", "VerifyPack", "Home", new { ProductCodeScheme = @item.ProductCodeScheme, ProductCode = @item.ProductCode, SerialNumber = @item.SerialNumber, Batch = @item.Batch, ExpirationDate = @item.ExpirationDate, CommandStatusCode = 0 }, 
                 new AjaxOptions { HttpMethod = "POST", 
                                   InsertionMode = InsertionMode.Replace, 
                                   UpdateTargetId = "targetElementId", 
                                   OnComplete = "onComplete();" 
                                 },
                 new { @class = "text-info" })

Примечание:

Если вам нужно обработать запрос AJAX и обычный запрос от одного контроллера, вы можете различить их использование Request.IsAjaxRequest() (или Context.Request.Headers["X-Requested-With"] == "XMLHttpRequest" в Core MVC).

10
задан 8 February 2009 в 07:55
поделиться

6 ответов

Согласно "Доменному Дизайну Диска Eric Evan" Вам нужен шаблон спецификации. Что-то вроде этого

public interface ISpecification<T>
{
  bool Matches(T instance);
  string GetSql();
}

public class ProductCategoryNameSpecification : ISpecification<Product>
{
  readonly string CategoryName;
  public ProductCategoryNameSpecification(string categoryName)
  {
    CategoryName = categoryName;
  }

  public bool Matches(Product instance)
  {
    return instance.Category.Name == CategoryName;
  }

  public string GetSql()
  {
    return "CategoryName like '" + { escaped CategoryName } + "'";
  }
}

Ваш репозиторий можно теперь назвать со спецификациями

var specifications = new List<ISpecification<Product>>();
specifications.Add(
 new ProductCategoryNameSpecification("Tops"));
specifications.Add(
 new ProductColorSpecification("Blue"));

var products = ProductRepository.GetBySpecifications(specifications);

Вы могли также создать универсальный класс CompositeSpecification, который будет содержать sub спецификации и индикатор относительно который логический оператор относиться к ним И/ИЛИ

Я был бы более склонен объединить выражения LINQ все же.

Обновление - Пример LINQ во времени выполнения

var product = Expression.Parameter(typeof(Product), "product");
var categoryNameExpression = Expression.Equal(
  Expression.Property(product, "CategoryName"),
  Expression.Constant("Tops"));

Можно добавить "и" как так

var colorExpression = Expression.Equal(
  Expression.Property(product, "Color"),
  Expression.Constant("Red"));
var andExpression = Expression.And(categoryNameExpression, colorExpression);

Наконец можно преобразовать это выражение в предикат и затем выполнить его...

var predicate = 
  (Func<Product, bool>)Expression.Lambda(andExpression, product).Compile();
var query = Enumerable.Where(YourDataContext.Products, predicate);

foreach(Product currentProduct in query)
  meh(currentProduct);

Вероятно, привычка компилирует, потому что я ввел ее непосредственно в браузер, но я полагаю, что это обычно корректно.

Другое обновление :-)

List<Product> products = new List<Product>();
products.Add(new Product { CategoryName = "Tops", Color = "Red" });
products.Add(new Product { CategoryName = "Tops", Color = "Gree" });
products.Add(new Product { CategoryName = "Trousers", Color = "Red" });
var query = (IEnumerable<Product>)products;
query = query.Where(p => p.CategoryName == "Tops");
query = query.Where(p => p.Color == "Red");
foreach (Product p in query)
    Console.WriteLine(p.CategoryName + " / " + p.Color);
Console.ReadLine();

В этом случае Вы оценили бы в памяти, потому что источником является Список, но если Ваш источник был контекстом данных, который поддерживал Linq2SQL, например, я думаю, что это оценило бы использование SQL.

Вы могли все еще использовать шаблон Спецификации для создания понятий явными.

public class Specification<T>
{
  IEnumerable<T> AppendToQuery(IEnumerable<T> query);
}

Основное различие между двумя подходами - то, что последние сборки известный запрос на основе явных свойств, тогда как первый мог использоваться для создания запроса любой структуры (такой как создание запроса полностью от XML, например.)

Этого должно быть достаточно для запущения Вас :-)

13
ответ дан 3 December 2019 в 22:02
поделиться

Стратегическая модель не обязательно вяжет хорошо с основанным на едином интерфейсе подходом репозитория. Лично, я, вероятно, пошел бы одним из двух путей сюда:

  • Один метод поиска, который поддерживает комбинации опций:

    IList<Product> GetProducts(string category, string store, ...);

(затем выборочно примените комбинации фильтров (т.е. null означает "любого") - или при создании команды, или передайте к SPROC, который делает что-то подобное.

  • С LINQ, возможно, выражение предиката?

    IList<Product> GetProducts(Expression<Func<Product,bool>> predicate);

Конечно, с LINQ Вы могли также использовать состав вызывающей стороны, но это более твердо записать закрытый / полностью протестированный репозиторий для:

 `IQueryable<Product> Products {get;}`

(и сделайте, чтобы вызывающая сторона использовала.Where (x => x. Категория == "нечто")) - я не так уверен в этом последнем долгосрочном...

2
ответ дан 3 December 2019 в 22:02
поделиться

Я думаю, что сделал бы класс Категории и класс Хранилища вместо просто строк:

class Category
{
  public Category(string s)
  {
    ...
  }
  ...
}

И затем возможно:

Product.GetProducts(
  Category category, //if this is null then don't filter on category
  Store store //if this is null then don't filter on store
  )
{
  ...
}

Category и Store классы могли бы быть связаны (они могли бы оба быть подклассами a Filter класс).

1
ответ дан 3 December 2019 в 22:02
поделиться

Я отвечаю на это на основе своего небольшого знания шаблонов.

Шаблон "декоратор" мог бы помочь здесь (полагающий, что можно добавить фильтр и получить результаты. Примените новые фильтры на него и получите новые результаты),

0
ответ дан 3 December 2019 в 22:02
поделиться

Я пошел бы с чем-то как стратегия самих фильтров и записал бы классы CategoryFilter и StoreFilter. Затем я использовал бы составной объект или декоратора для объединения фильтров.

0
ответ дан 3 December 2019 в 22:02
поделиться

Вы не можете только добавить, Где материал, поскольку Вы идете сюда?

var products = datacontext.Products;

if(!String.IsNullOrEmpty(type))
  products = products.Where(p => p.Type == type);

if(!String.IsNullOrEmpty(store))
  products = products.Where(p => p.Store == store);

foreach(var p in products)
  // Do whatever

или что-то как этот...

0
ответ дан 3 December 2019 в 22:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: