Place order function in NopCommerce 4.5 - c#
and I want to create a custom controller with a place order function.
I'm using the below code:
private async Task<Order> PlaceOrder(IList<ShoppingCartItem> cart)
{
var _orderProcessingService = EngineContext.Current.Resolve<IOrderProcessingService>();
var _genericAttributeService = EngineContext.Current.Resolve<IGenericAttributeService>();
var processPaymentRequest = HttpContext.Session.Get<ProcessPaymentRequest>("OrderPaymentInfo") ?? new ProcessPaymentRequest();
_paymentService.GenerateOrderGuid(processPaymentRequest);
processPaymentRequest.StoreId = (await _storeContext.GetCurrentStoreAsync()).Id;
processPaymentRequest.CustomerId = (await _workContext.GetCurrentCustomerAsync()).Id;
processPaymentRequest.PaymentMethodSystemName = await _genericAttributeService.GetAttributeAsync<string>(await _workContext.GetCurrentCustomerAsync(),
NopCustomerDefaults.SelectedPaymentMethodAttribute, (await _storeContext.GetCurrentStoreAsync()).Id);
HttpContext.Session.Set<ProcessPaymentRequest>("OrderPaymentInfo", processPaymentRequest);
var placeOrderResult = await _orderProcessingService.PlaceOrderAsync(processPaymentRequest);
if (placeOrderResult.Success)
{
HttpContext.Session.Set<ProcessPaymentRequest>("OrderPaymentInfo", null);
var postProcessPaymentRequest = new PostProcessPaymentRequest
{
Order = placeOrderResult.PlacedOrder
};
await _paymentService.PostProcessPaymentAsync(postProcessPaymentRequest);
return postProcessPaymentRequest.Order;
}
else
{
return null;
}
}
But where can call the function to place an order and clear the cart?
I'm working on nopcommerce 4.5
You can override checkout controller and action method for confirm order or simply override PlaceOrder method from OrderProcessingService and do you custom changes.
As you are working on the custom plugin so the better way is to override the PlaceOrderAsync method.
Below is the code for override OrderProcessingService service from the plugin. I consider NivoSlider for example.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Nop.Core;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Common;
using Nop.Core.Domain.Customers;
using Nop.Core.Domain.Directory;
using Nop.Core.Domain.Discounts;
using Nop.Core.Domain.Localization;
using Nop.Core.Domain.Logging;
using Nop.Core.Domain.Orders;
using Nop.Core.Domain.Payments;
using Nop.Core.Domain.Shipping;
using Nop.Core.Domain.Tax;
using Nop.Core.Domain.Vendors;
using Nop.Core.Events;
using Nop.Services.Affiliates;
using Nop.Services.Catalog;
using Nop.Services.Common;
using Nop.Services.Customers;
using Nop.Services.Directory;
using Nop.Services.Discounts;
using Nop.Services.Localization;
using Nop.Services.Logging;
using Nop.Services.Messages;
using Nop.Services.Orders;
using Nop.Services.Payments;
using Nop.Services.Security;
using Nop.Services.Shipping;
using Nop.Services.Stores;
using Nop.Services.Tax;
using Nop.Services.Vendors;
namespace Nop.Plugin.Widgets.NivoSlider.Services
{
/// <summary>
/// Order processing service
/// </summary>
public partial class CustomOrderProcessingService : OrderProcessingService , IOrderProcessingService
{
#region Fields
private readonly CurrencySettings _currencySettings;
private readonly IAddressService _addressService;
private readonly IAffiliateService _affiliateService;
private readonly ICheckoutAttributeFormatter _checkoutAttributeFormatter;
private readonly ICountryService _countryService;
private readonly ICurrencyService _currencyService;
private readonly ICustomerActivityService _customerActivityService;
private readonly ICustomerService _customerService;
private readonly ICustomNumberFormatter _customNumberFormatter;
private readonly IDiscountService _discountService;
private readonly IEncryptionService _encryptionService;
private readonly IEventPublisher _eventPublisher;
private readonly IGenericAttributeService _genericAttributeService;
private readonly IGiftCardService _giftCardService;
private readonly ILanguageService _languageService;
private readonly ILocalizationService _localizationService;
private readonly ILogger _logger;
private readonly IOrderService _orderService;
private readonly IOrderTotalCalculationService _orderTotalCalculationService;
private readonly IPaymentPluginManager _paymentPluginManager;
private readonly IPaymentService _paymentService;
private readonly IPdfService _pdfService;
private readonly IPriceCalculationService _priceCalculationService;
private readonly IPriceFormatter _priceFormatter;
private readonly IProductAttributeFormatter _productAttributeFormatter;
private readonly IProductAttributeParser _productAttributeParser;
private readonly IProductService _productService;
private readonly IReturnRequestService _returnRequestService;
private readonly IRewardPointService _rewardPointService;
private readonly IShipmentService _shipmentService;
private readonly IShippingService _shippingService;
private readonly IShoppingCartService _shoppingCartService;
private readonly IStateProvinceService _stateProvinceService;
private readonly IStoreService _storeService;
private readonly ITaxService _taxService;
private readonly IVendorService _vendorService;
private readonly IWebHelper _webHelper;
private readonly IWorkContext _workContext;
private readonly IWorkflowMessageService _workflowMessageService;
private readonly LocalizationSettings _localizationSettings;
private readonly OrderSettings _orderSettings;
private readonly PaymentSettings _paymentSettings;
private readonly RewardPointsSettings _rewardPointsSettings;
private readonly ShippingSettings _shippingSettings;
private readonly TaxSettings _taxSettings;
#endregion
#region Ctor
public CustomOrderProcessingService(CurrencySettings currencySettings,
IAddressService addressService,
IAffiliateService affiliateService,
ICheckoutAttributeFormatter checkoutAttributeFormatter,
ICountryService countryService,
ICurrencyService currencyService,
ICustomerActivityService customerActivityService,
ICustomerService customerService,
ICustomNumberFormatter customNumberFormatter,
IDiscountService discountService,
IEncryptionService encryptionService,
IEventPublisher eventPublisher,
IGenericAttributeService genericAttributeService,
IGiftCardService giftCardService,
ILanguageService languageService,
ILocalizationService localizationService,
ILogger logger,
IOrderService orderService,
IOrderTotalCalculationService orderTotalCalculationService,
IPaymentPluginManager paymentPluginManager,
IPaymentService paymentService,
IPdfService pdfService,
IPriceCalculationService priceCalculationService,
IPriceFormatter priceFormatter,
IProductAttributeFormatter productAttributeFormatter,
IProductAttributeParser productAttributeParser,
IProductService productService,
IReturnRequestService returnRequestService,
IRewardPointService rewardPointService,
IShipmentService shipmentService,
IShippingService shippingService,
IShoppingCartService shoppingCartService,
IStateProvinceService stateProvinceService,
IStoreService storeService,
ITaxService taxService,
IVendorService vendorService,
IWebHelper webHelper,
IWorkContext workContext,
IWorkflowMessageService workflowMessageService,
LocalizationSettings localizationSettings,
OrderSettings orderSettings,
PaymentSettings paymentSettings,
RewardPointsSettings rewardPointsSettings,
ShippingSettings shippingSettings,
TaxSettings taxSettings) :base(currencySettings,
addressService,
affiliateService,
checkoutAttributeFormatter,
countryService,
currencyService,
customerActivityService,
customerService,
customNumberFormatter,
discountService,
encryptionService,
eventPublisher,
genericAttributeService,
giftCardService,
languageService,
localizationService,
logger,
orderService,
orderTotalCalculationService,
paymentPluginManager,
paymentService,
pdfService,
priceCalculationService,
priceFormatter,
productAttributeFormatter,
productAttributeParser,
productService,
returnRequestService,
rewardPointService,
shipmentService,
shippingService,
shoppingCartService,
stateProvinceService,
storeService,
taxService,
vendorService,
webHelper,
workContext,
workflowMessageService,
localizationSettings,
orderSettings,
paymentSettings,
rewardPointsSettings,
shippingSettings,
taxSettings)
{
_currencySettings = currencySettings;
_addressService = addressService;
_affiliateService = affiliateService;
_checkoutAttributeFormatter = checkoutAttributeFormatter;
_countryService = countryService;
_currencyService = currencyService;
_customerActivityService = customerActivityService;
_customerService = customerService;
_customNumberFormatter = customNumberFormatter;
_discountService = discountService;
_encryptionService = encryptionService;
_eventPublisher = eventPublisher;
_genericAttributeService = genericAttributeService;
_giftCardService = giftCardService;
_languageService = languageService;
_localizationService = localizationService;
_logger = logger;
_orderService = orderService;
_orderTotalCalculationService = orderTotalCalculationService;
_paymentPluginManager = paymentPluginManager;
_paymentService = paymentService;
_pdfService = pdfService;
_priceCalculationService = priceCalculationService;
_priceFormatter = priceFormatter;
_productAttributeFormatter = productAttributeFormatter;
_productAttributeParser = productAttributeParser;
_productService = productService;
_returnRequestService = returnRequestService;
_rewardPointService = rewardPointService;
_shipmentService = shipmentService;
_shippingService = shippingService;
_shoppingCartService = shoppingCartService;
_stateProvinceService = stateProvinceService;
_storeService = storeService;
_taxService = taxService;
_vendorService = vendorService;
_webHelper = webHelper;
_workContext = workContext;
_workflowMessageService = workflowMessageService;
_localizationSettings = localizationSettings;
_orderSettings = orderSettings;
_paymentSettings = paymentSettings;
_rewardPointsSettings = rewardPointsSettings;
_shippingSettings = shippingSettings;
_taxSettings = taxSettings;
}
#endregion
#region Methods
public override async Task<PlaceOrderResult> PlaceOrderAsync(ProcessPaymentRequest processPaymentRequest)
{
if (processPaymentRequest == null)
throw new ArgumentNullException(nameof(processPaymentRequest));
var result = new PlaceOrderResult();
try
{
if (processPaymentRequest.OrderGuid == Guid.Empty)
throw new Exception("Order GUID is not generated");
//prepare order details
var details = await PreparePlaceOrderDetailsAsync(processPaymentRequest);
var processPaymentResult = await GetProcessPaymentResultAsync(processPaymentRequest, details);
if (processPaymentResult == null)
throw new NopException("processPaymentResult is not available");
if (processPaymentResult.Success)
{
var order = await SaveOrderDetailsAsync(processPaymentRequest, processPaymentResult, details);
result.PlacedOrder = order;
//move shopping cart items to order items
await MoveShoppingCartItemsToOrderItemsAsync(details, order);
//discount usage history
await SaveDiscountUsageHistoryAsync(details, order);
//gift card usage history
await SaveGiftCardUsageHistoryAsync(details, order);
//recurring orders
if (details.IsRecurringShoppingCart)
await CreateFirstRecurringPaymentAsync(processPaymentRequest, order);
//notifications
await SendNotificationsAndSaveNotesAsync(order);
//reset checkout data
await _customerService.ResetCheckoutDataAsync(details.Customer, processPaymentRequest.StoreId, clearCouponCodes: true, clearCheckoutAttributes: true);
await _customerActivityService.InsertActivityAsync("PublicStore.PlaceOrder",
string.Format(await _localizationService.GetResourceAsync("ActivityLog.PublicStore.PlaceOrder"), order.Id), order);
//raise event
await _eventPublisher.PublishAsync(new OrderPlacedEvent(order));
//check order status
await CheckOrderStatusAsync(order);
if (order.PaymentStatus == PaymentStatus.Paid)
await ProcessOrderPaidAsync(order);
}
else
foreach (var paymentError in processPaymentResult.Errors)
result.AddError(string.Format(await _localizationService.GetResourceAsync("Checkout.PaymentError"), paymentError));
}
catch (Exception exc)
{
await _logger.ErrorAsync(exc.Message, exc);
result.AddError(exc.Message);
}
if (result.Success)
return result;
//log errors
var logError = result.Errors.Aggregate("Error while placing order. ",
(current, next) => $"{current}Error {result.Errors.IndexOf(next) + 1}: {next}. ");
var customer = await _customerService.GetCustomerByIdAsync(processPaymentRequest.CustomerId);
await _logger.ErrorAsync(logError, customer: customer);
return result;
}
#endregion
}
}
Then the DI for the custom service at startup.
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Nop.Core.Infrastructure;
using Nop.Plugin.Widgets.NivoSlider.Services;
using Nop.Services.Messages;
using Nop.Services.Orders;
using Nop.Web.Framework.Infrastructure.Extensions;
namespace Nop.Plugin.Widgets.NivoSlider.Infrastructure
{
/// <summary>
/// Represents object for the configuring services on application startup
/// </summary>
public class NopStartup : INopStartup
{
/// <summary>
/// Add and configure any of the middleware
/// </summary>
/// <param name="services">Collection of service descriptors</param>
/// <param name="configuration">Configuration of the application</param>
public void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
//override services
services.AddScoped<IOrderProcessingService, CustomOrderProcessingService>();
}
/// <summary>
/// Configure the using of added middleware
/// </summary>
/// <param name="application">Builder for configuring an application's request pipeline</param>
public void Configure(IApplicationBuilder application)
{
}
/// <summary>
/// Gets order of this startup configuration implementation
/// </summary>
public int Order => 2001;
}
}
It should work for 4.6, 4.5 and 4.4 of nopCommerce version. Tested for 4.6
Related
What unit tests would be better or redudant
I started to learn a new topic for me - unit testing. Ffter writing a few tests, I began to wonder what else can be written and whether it will not be redundant. If you write code examples it would be even better for me, thank you. For example do i need to write same Assert.ThrowsAsync<NullReferenceException> test for method ChooseFilmToWatchWithChilds or it will be redundant /// <summary> /// Check if database returns null /// </summary> [Fact] public void NoFilmsInDatabase_ExceptionReturns() { Assert.ThrowsAsync<NullReferenceException>( async () => { await _homeFilmHandler.IndicateFavouritesOfOurFilms(); }); } Like this /// <summary> /// Check if database returns null /// </summary> [Fact] public void NoFilmsInDatabaseChooseFilmToWatchWithChilds_ExceptionReturns() { Assert.ThrowsAsync<NullReferenceException>( async () => { await _homeFilmHandler.ChooseFilmToWatchWithChilds(); }); } Implementation class using VideoArchive.Contracts.Abstractions.Data; using VideoArchive.Contracts.Abstractions.FilmServices; using VideoArchive.Contracts.Abstractions.Integrations; using VideoArchive.Contracts.Models; using VideoArchive.Contracts.Models.Home; namespace VideoArchive.Implementations.FilmServices { public class HomeFilmHandler : IHomeFilmHandler { #region Constructors and DI private readonly IFakeDatabaseService _fakeDatabaseService; private readonly IFakeInegrationService _fakeInegrationService; private readonly IMapper _mapper; public HomeFilmHandler( IFakeDatabaseService fakeDatabaseService, IFakeInegrationService fakeInegrationService, IMapper mapper) { _fakeDatabaseService = fakeDatabaseService; _fakeInegrationService = fakeInegrationService; _mapper = mapper; } #endregion public async Task<HomeFilm> ChooseFilmToWatchWithChilds() { var allFilms = await _fakeDatabaseService.GetAllFilms(); var filmToWatch = allFilms .Where(film => film.IsFavorite) .OrderByDescending(film => film.TimesWatched); foreach (var film in filmToWatch) { if (_fakeInegrationService.GetAgeRestrictions(_mapper.Map<Film>(film)) <= 6) { return film; } } return await Task.FromResult<HomeFilm>(null); } public async Task IndicateFavouritesOfOurFilms() { var allFilms = await _fakeDatabaseService.GetAllFilms(); if (!allFilms.Any() || allFilms == null) { throw new NullReferenceException(); } IndicateFilms(allFilms); } private async void IndicateFilms(List<HomeFilm> films) { foreach (var film in films) { if (film.TimesWatched >= 5) { film.IsFavorite = true; await _fakeDatabaseService.UpdateFilm(film, film.Id); } } } } } TestsClass using AutoMapper; using VideoArchive.Contracts.Abstractions.Data; using VideoArchive.Contracts.Abstractions.Integrations; using VideoArchive.Contracts.Models.Home; using VideoArchive.Implementations.FilmServices; using Moq; using Xunit; namespace VideoArchive.Tests { public class HomeFilmHandlerTests { private readonly Fixture _fixture = new Fixture(); private readonly Mock<IFakeDatabaseService> _fakeDatabaseService = new Mock<IFakeDatabaseService>(); private readonly Mock<IFakeInegrationService> _fakeIntegrationService = new Mock<IFakeInegrationService>(); private readonly Mock<IMapper> _mapper = new Mock<IMapper>(); private readonly List<HomeFilm> _homeFilms; private readonly HomeFilmHandler _homeFilmHandler; public HomeFilmHandlerTests() { _homeFilms = _fixture.CreateMany<HomeFilm>().ToList(); _fakeDatabaseService .Setup(service => service .GetAllFilms()) .ReturnsAsync(_homeFilms); _fakeDatabaseService .Setup(service => service .UpdateFilm(It.IsAny<HomeFilm>(), It.IsAny<int>())); _fakeIntegrationService .Setup(service => service .GetAgeRestrictions(It.IsAny<HomeFilm>())); _homeFilmHandler = new HomeFilmHandler( _fakeDatabaseService.Object, _fakeIntegrationService.Object, _mapper.Object); } [Fact] public void NoFilmsInDatabase_ExceptionReturns() { Assert.ThrowsAsync<NullReferenceException>(async () => { await _homeFilmHandler.IndicateFavouritesOfOurFilms(); }); } [Fact] public async void FilmsAreIndicatedRightTimes_UpdateFilmCalled() { var filmCountThatNeededToIndicate = _homeFilms.Where(film => film.TimesWatched >= 5).Count(); await _homeFilmHandler.IndicateFavouritesOfOurFilms(); _fakeDatabaseService.Verify( service => service.UpdateFilm(It.IsAny<HomeFilm>(), It.IsAny<int>()), Times.Exactly(filmCountThatNeededToIndicate)); } [Fact] public void FilmWithChild() { //Write test here } } } FakeDatabaseService using AutoFixture; using VideoArchive.Contracts.Abstractions.Data; using VideoArchive.Contracts.Models.Home; namespace VideoArchive.Implementations.Data.Fake { /// <summary> /// Fake service imitating databaseService /// </summary> public class FakeDatabaseService : IFakeDatabaseService { private readonly Fixture Fixture = new Fixture(); public async Task<List<HomeFilm>> GetAllFilms() { return Fixture.CreateMany<HomeFilm>().ToList(); } public async Task<HomeFilm> GetFilmById(int id) { return Fixture.Build<HomeFilm>().With(film => film.Id, id).Create(); } public async Task UpdateFilm(HomeFilm film, int id) { // Logic to updating film } } } FakeInegrationService namespace VideoArchive.Contracts.Abstractions.Integrations { public interface IFakeIntegrationService { public int GetAgeRestrictions(IFilm film); } }
Testing that both method throw some exception is not redundant. Each method has its own behavior. The fact that they behave similarly doesn't change that. What to test next? I suggest you check Microsoft's Unit testing best practices for some insights. However, if you feel that your tests are redundant, it could be a sign that your architecture can be improved. Example: If you change the constructor of HomeFilmHandler so that it throws an ArgumentNullException when its fakeDatabaseService parameter is null, you could replace the 2 tests that checks the NullReferenceException by 1 test that checks that the constructor of HomeFilmHandler throws when the fakeDatabaseService is null. This is just an example to illustrate the point.
Is it possible to gain code coverage for constructors with unit tests?
Say I have these private fields and this constructor... private readonly ILogger<KafkaFactory<T>> _logger; private readonly IKafkaConfig _kafkaConfig; private readonly IOptionsMonitor<IKafkaConfig>? _kafkaConfigMonitor = null; private readonly string? _configName = null; private IKafkaConfig Options => _configName == null ? _kafkaConfigMonitor?.CurrentValue ?? _kafkaConfig : _kafkaConfigMonitor!.Get(_configName); public KafkaFactory(ILogger<KafkaFactory<T>> logger, IOptionsMonitor<IKafkaConfig> kafkaConfig, string name) { _logger = logger; _kafkaConfigMonitor = kafkaConfig; _configName = name; _kafkaConfig = kafkaConfig.Get(name); _logger.LogInformation("{class} using named options {options}", nameof(KafkaFactory<T>), Options); } How do I cover this code with unit tests? Is this even possible?
No manifests exist for the current culture using IStringLocalizer
I'm developing backend application using .NET core 3.1. I moved CommonResource from my old project (.NET core 2.1) where works fine. I want to obtain value for key in specified culture. Implementation of CommonResource: public class CommonResource : ICommonResource { private readonly IStringLocalizer<SharedResource> _localizer; public CommonResource( IStringLocalizer<SharedResource> localizer) { _localizer = localizer; } #region ICommonResource Members #region General public string AppName( string language) => GetString(language, nameof(AppName)); #endregion #endregion /// <summary> /// Dispose of class and parent classes /// </summary> public void Dispose() => GC.SuppressFinalize(this); private string GetString( string language, string name) { var currentCulture = CultureInfo.CurrentCulture; CultureInfo.CurrentCulture = new CultureInfo(language); var value = _localizer[name]; CultureInfo.CurrentCulture = currentCulture; // TEST - check all string //var result = _localizer.GetAllStrings(); return value; } } LocalizationExtensions with AddDefaultLocalization method: public static class LocalizationExtensions { private const bool AcceptLanguageHeaderRequestCultureProvider = false; private static readonly CultureInfo CultureInfoEnUs = new CultureInfo("en-US"); private static readonly CultureInfo CultureInfoPlPl = new CultureInfo("pl-PL"); private static readonly CultureInfo DefaultRequestCulture = CultureInfoEnUs; private static readonly CultureInfo[] SupportedCultures = { CultureInfoEnUs, CultureInfoPlPl }; public static void AddDefaultLocalization( this IServiceCollection serviceCollection) { serviceCollection.AddLocalization(); serviceCollection.Configure<RequestLocalizationOptions>( options => { options.DefaultRequestCulture = new RequestCulture(DefaultRequestCulture, DefaultRequestCulture); options.SupportedCultures = SupportedCultures; if (!AcceptLanguageHeaderRequestCultureProvider) { //https://stackoverflow.com/questions/44480759/asp-net-core-default-language-is-always-english options.RequestCultureProviders = new List<IRequestCultureProvider> { new QueryStringRequestCultureProvider(), new CookieRequestCultureProvider() }; } }); } } My SharedResources are in Resources path (Build Action: Embedded resource and Access Modifier: No code generation). Unfortunately invoke _localizer.GetAllStrings(); generates exception "No manifests exist for the current culture". I tried many solutions e.g. move SharedResources to root path or install extra nuget package, but nothing helped. Do you have any idea why in new version .net core this problem exists? Thanks for help!
.Net core 3.1 return RedirectToPage("SomePage") not working as expecting
I am on the Dashboard page where I have inherited my base class, which is expecting redirection based on value. I actually don't want to display page of value is 0. Below is the code. This is the main page I don't want to execute the OnGet() on the dashboard page. Before that, I have to check some values on HostBasePage [Area("BusinessHost")] [Authorize(Roles ="Host")] public class dashboardModel : HostBasePage { public dashboardModel(IAccountBusinessRepository accountBusinessRepository, ISessionManager sessionManager) : base(accountBusinessRepository, sessionManager) { } public void OnGet() { } } This is my base class and I want to go to the "AccountSetup" page. public class HostBasePage : PageModel { private readonly IAccountBusinessRepository _accountBusinessRepository; private readonly ISessionManager _sessionManager; public HostBasePage(IAccountBusinessRepository accountBusinessRepository, ISessionManager sessionManager) { _sessionManager = sessionManager; _accountBusinessRepository = accountBusinessRepository; ValidateAccount(); } /// <summary> /// Validate Host account. /// Account setup and payment needs to me complated. /// </summary> private async Task<IActionResult> ValidateAccount() { try { var accountID = _sessionManager.GetSessionValue("AccountID"); HostProfileValidateModel obj = await _accountBusinessRepository.HostProfileValidate(Convert.ToInt32(accountID)); if (obj.IsAccountSetup == 0) { return RedirectToPage("AccountSetup"); } //if (obj.IsPaid == 0) // throw new Exception(""); return Page(); } catch (Exception ex) { throw ex; } } If obj.IsAccountSetup is 0, I need redirection. No error is comming right now, but it's not redirecting to the AccountSetup page. This is the page I want to display. [Area("BusinessHost")] [Authorize(Roles = "Host")] public class AccountSetupModel : PageModel { private readonly IAccountBusinessRepository _accountBusinessRepository; private readonly IServiceBusinessRepository _serviceBusinessRepository; private readonly ICategoryBusinessRepository _categoryBusinessRepository; private readonly IFranchiseBusinessRepository _franchiseBusinessRepository; private readonly ISessionManager _sessionManager; private readonly IPlansBusinessRepository _plansBusinessRepository; private readonly IBusinessHostAccountSetupRepository _businessHostAccountSetupRepository; public AccountSetupModel(IBusinessHostAccountSetupRepository businessHostAccountSetupRepository, IAccountBusinessRepository accountBusinessRepository,IPlansBusinessRepository plansBusinessRepository , ISessionManager sessionManager, ICategoryBusinessRepository categoryBusinessRepository, IServiceBusinessRepository serviceBusinessRepository, IFranchiseBusinessRepository franchiseBusinessRepository) { _accountBusinessRepository = accountBusinessRepository; _serviceBusinessRepository = serviceBusinessRepository; _categoryBusinessRepository = categoryBusinessRepository; _franchiseBusinessRepository = franchiseBusinessRepository; _sessionManager = sessionManager; _businessHostAccountSetupRepository = businessHostAccountSetupRepository; _plansBusinessRepository = plansBusinessRepository; } public async void OnGet() { string email = _sessionManager.GetSessionValue("RegisterEmail"); ModelServiceModel = new ServicesModel(); ModelCategoryModel = new ServicesModel(); ModelFranchiseModel = new FranchiseModel(); GetAllAccountData(); GetAllCategories(); GetAllServices(); GetAllFranchise(); PlansModel = await _plansBusinessRepository.GetAllPlans(); if (PlansModel != null) { PlansModel.TotalAmmount = PlansModel.AccountSetupCharges + PlansModel.MonthlyCharges + PlansModel.FrontDeskCharges; } } public void GetAllCategories() { var data = _categoryBusinessRepository.GetAllCategoriesList(); ModelServiceModel.Category = data.Result.Select(x => new SelectListItem { Text = Convert.ToString(x.CategoryName), Value = Convert.ToString(x.CategoryID) }).ToList(); } }
You could just implement OnPageHandlerExecutionAsync methods in your PageModel like public class HostBasePage : PageModel { private readonly IAccountBusinessRepository _accountBusinessRepository; private readonly ISessionManager _sessionManager; public HostBasePage(IAccountBusinessRepository accountBusinessRepository, ISessionManager sessionManager) { _sessionManager = sessionManager; _accountBusinessRepository = accountBusinessRepository; } public override async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next) { try { var accountID = _sessionManager.GetSessionValue("AccountID"); HostProfileValidateModel obj = await _accountBusinessRepository.HostProfileValidate(Convert.ToInt32(accountID)); if (obj.IsAccountSetup == 0) { context.Result = RedirectToPage("/AccountSetup", new { area = "BusinessHost" }); } else { await next.Invoke(); } } catch (Exception ex) { throw ex; } } } Refer to https://learn.microsoft.com/en-us/aspnet/core/razor-pages/filter?view=aspnetcore-3.1#implement-razor-page-filters-by-overriding-filter-methods
Service call to service at Aspnet Zero Boilerplate
I have a couple of simple services that exchange information: public class Service2: PPlusAppServiceBase { private readonly IAbpSession _session; public Service2(IAbpSession session) { _session = session; } public Entity getEntity() { Entity et = new Entity(); Service1 _service1 = new Service1(_session); [...] _service1.getEntity(); [...] return et; } } public class Service1: PPlusAppServiceBase { private readonly IAbpSession _session; public Service1(IAbpSession session) { _session = session; } public Entity getEntity() { _session.[...] return et; } } OK, it works properly and I just have to send the session to work. But how can I do it simply when I have to get information from a more complex service? Like the default Boilerplate? For example, EditionAppService: public class EditionAppService : PPlusAppServiceBase, IEditionAppService { private readonly EditionManager _editionManager; private readonly IRepository<SubscribableEdition> _editionRepository; private readonly IRepository<Tenant> _tenantRepository; private readonly IBackgroundJobManager _backgroundJobManager; public EditionAppService( EditionManager editionManager, IRepository<SubscribableEdition> editionRepository, IRepository<Tenant> tenantRepository, IBackgroundJobManager backgroundJobManager) { _editionManager = editionManager; _editionRepository = editionRepository; _tenantRepository = tenantRepository; _backgroundJobManager = backgroundJobManager; } [AbpAuthorize(AppPermissions.Pages_Editions)] public async Task<ListResultDto<EditionListDto>> GetEditions() { var editions = await (from edition in _editionRepository.GetAll() join expiringEdition in _editionRepository.GetAll() on edition.ExpiringEditionId equals expiringEdition.Id into expiringEditionJoined from expiringEdition in expiringEditionJoined.DefaultIfEmpty() select new { Edition = edition, expiringEditionDisplayName = expiringEdition.DisplayName }).ToListAsync(); var result = new List<EditionListDto>(); foreach (var edition in editions) { var resultEdition = ObjectMapper.Map<EditionListDto>(edition.Edition); resultEdition.ExpiringEditionDisplayName = edition.expiringEditionDisplayName; result.Add(resultEdition); } return new ListResultDto<EditionListDto>(result); } } As you can see, the constructor is more complex, the constructor data comes directly defined by swagger (ASP.NET Boilerplate creates dynamic drivers and swagger, and it is these that carry this data that they use as a builder), but when making the call from another service I can't get them. What is the best way to do that is edit the minimum the second? In Service2, where I have to call EditionAppService.GetEditions I need something like: EditionAppService _editionAppService = new EditionAppService(); _editionAppService.GetEditions().Result; But wait for the builder I don't have
That design pattern is called Dependency Injection. Do this instead: public class Service2: PPlusAppServiceBase { private readonly EditionAppService _editionAppService; // Add this private readonly Service1 _service1; // Add this private readonly IAbpSession _session; public Service2( EditionAppService editionAppService, // Add this Service1 service1, // Add this IAbpSession session) { _editionAppService = editionAppService; // Add this _service1 = service1; // Add this _session = session; } public Entity getEntity() { Entity et = new Entity(); // Service1 _service1 = new Service1(_session); // Remove this // ... _service1.getEntity(); // ... return et; } // ... } Related: Should I be calling an AppService from another AppService?