В основном @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).
Согласно "Доменному Дизайну Диска 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, например.)
Этого должно быть достаточно для запущения Вас :-)
Стратегическая модель не обязательно вяжет хорошо с основанным на едином интерфейсе подходом репозитория. Лично, я, вероятно, пошел бы одним из двух путей сюда:
Один метод поиска, который поддерживает комбинации опций:
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. Категория == "нечто")) - я не так уверен в этом последнем долгосрочном...
Я думаю, что сделал бы класс Категории и класс Хранилища вместо просто строк:
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
класс).
Я отвечаю на это на основе своего небольшого знания шаблонов.
Шаблон "декоратор" мог бы помочь здесь (полагающий, что можно добавить фильтр и получить результаты. Примените новые фильтры на него и получите новые результаты),
Я пошел бы с чем-то как стратегия самих фильтров и записал бы классы CategoryFilter и StoreFilter. Затем я использовал бы составной объект или декоратора для объединения фильтров.
Вы не можете только добавить, Где материал, поскольку Вы идете сюда?
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
или что-то как этот...