Action Filter for DownloadCatalogAsPdf

4 months ago
I am trying to create an action filter for DownloadCatalogAsPdf method in Admin ProductController.

So far I created a new "ListingController" in my plugin.

My controller method is;

[HttpPost, ActionName("List")]
    [FormValueRequired("download-catalog-pdf")]
    public virtual IActionResult DownloadCatalogAsPdf(ProductSearchModel model)
    {
        if (!_permissionService.Authorize(StandardPermissionProvider.ManageProducts))
            return AccessDeniedView();

        //a vendor should have access only to his products
        if (_workContext.CurrentVendor != null)
        {
            model.SearchVendorId = _workContext.CurrentVendor.Id;
        }

        var categoryIds = new List<int> { model.SearchCategoryId };
        //include subcategories
        if (model.SearchIncludeSubCategories && model.SearchCategoryId > 0)
            categoryIds.AddRange(_categoryService.GetChildCategoryIds(parentCategoryId: model.SearchCategoryId, showHidden: true));

        //0 - all (according to "ShowHidden" parameter)
        //1 - published only
        //2 - unpublished only
        bool? overridePublished = null;
        if (model.SearchPublishedId == 1)
            overridePublished = true;
        else if (model.SearchPublishedId == 2)
            overridePublished = false;

        var products = _productService.SearchProducts(
            categoryIds: categoryIds,
            manufacturerId: model.SearchManufacturerId,
            storeId: model.SearchStoreId,
            vendorId: model.SearchVendorId,
            warehouseId: model.SearchWarehouseId,
            productType: model.SearchProductTypeId > 0 ? (ProductType?)model.SearchProductTypeId : null,
            keywords: model.SearchProductName,
            showHidden: true,
            overridePublished: overridePublished);

        try
        {
            byte[] bytes;
            using (var stream = new MemoryStream())
            {
                _pdfService.PrintProductsToPdf(stream, products);
                bytes = stream.ToArray();
            }

            return File(bytes, MimeTypes.ApplicationPdf, "pdfcatalog.pdf");
        }
        catch (Exception exc)
        {
            _notificationService.ErrorNotification(exc);
            return RedirectToAction("List");
        }
    }
  

and my action filter;

public class UnfreightedActionFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {

        //Check Action and controller of the route and use it to redirect to your custom action or do any customization as per your requirement.
        var actionName = ((Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)context.ActionDescriptor).ActionName;
        var controllerName = ((Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)context.ActionDescriptor).ControllerName;

        //Admin Product
        if (!string.IsNullOrEmpty(controllerName) && !string.IsNullOrEmpty(actionName) && context.Controller is Web.Areas.Admin.Controllers.ProductController && actionName == "DownloadCatalogAsPdf")
        {
            switch (controllerName)
            {
                case "Product":
                    context.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Listing", action = "DownloadCatalogAsPdf" }));
                    break;

            }
        }

    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        //No implementation here. Do it as per your requirement
    }

}



I already registered the action filter in custom startup and when I create  other filters it works fine. Since it is in asp form in List.cshtml should I do anything else? It doesn't kick in my listing controller method. It still goes to product controller.
4 months ago
Hello dianoche

Are you registered the action filter in DependencyRegistrar.cs file?

If not then register it in DependencyRegistrar file.


builder.RegisterType<UnfreithedActionFilter>().As<IFilterProvider>();


Please follow with this link if you re not getting any things related to use action filter in nopcommerce.
4 months ago
Shegy wrote:
Hello dianoche

Are you registered the action filter in DependencyRegistrar.cs file?

If not then register it in DependencyRegistrar file.


builder.RegisterType<UnfreithedActionFilter>().As<IFilterProvider>();


Please follow with this link if you re not getting any things related to use action filter in nopcommerce.


I added it in my custom startup as;


services.AddMvc(options =>
            {
                //an instant  
                options.Filters.Add(new UnfreightedActionFilter());
                //By the type  
                options.Filters.Add(typeof(UnfreightedActionFilter));
            });


I don't think it supposed to be in DependencyRegistrar file.

all other action filters works fine except asp form download catalog as pdf one
4 months ago
I don't recall correctly why I used ActionFilterAttribute in my project instead of IActionFilter but that works for me. Also, the way I configured the custom filter is different. On my plugin startup code:


services.AddMvc(options =>
{
    options.Filters.Add<CustomActionFilter>();
});


Also, check if the logic hits the pipeline in the filter. Maybe your context and controller checking has something wrong in the logic. This check has been working for my case at least and it is more succinct compared to the other way in my opinion:

if (!(context.ActionDescriptor is ControllerActionDescriptor actionDescriptor)) // Pattern matching feature of C#
    return;

if (actionDescriptor.ControllerTypeInfo == typeof(ProductController) && actionDescriptor.ActionName == "NameOfAction" && context.HttpContext.Request.Method == "POST")
{
    // Do stuff here
}
4 months ago
Spincel, thanks for the reply. My action filter works fine with other methods. It does not kick in when I try to create an action filter for DownloadCatalogAsPdf method in Admin ProductController. I think since it is in asp form, needs a different approach.