Webiant Logo Webiant Logo
  1. No results found.

    Try your search with a different keyword or use * as a wildcard.

BaseController.cs

using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewComponents;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Mvc.ViewFeatures.Buffers;
using Microsoft.Extensions.Primitives;
using Nop.Core;
using Nop.Core.Events;
using Nop.Core.Http.Extensions;
using Nop.Core.Infrastructure;
using Nop.Services.Localization;
using Nop.Web.Framework.Events;
using Nop.Web.Framework.Models;
using Nop.Web.Framework.Mvc.Filters;
using Nop.Web.Framework.UI;

namespace Nop.Web.Framework.Controllers;

/// 
/// Base controller
/// 
[HttpsRequirement]
[PublishModelEvents]
[SignOutFromExternalAuthentication]
[ValidatePassword]
[SaveIpAddress]
[SaveLastActivity]
[SaveLastVisitedPage]
[ForceMultiFactorAuthentication]
public abstract partial class BaseController : Controller
{
    #region Rendering

    /// 
    /// Render component to string
    /// 
    /// Component type
    /// Arguments
    /// 
    /// A task that represents the asynchronous operation
    /// The task result contains the result
    /// 
    protected virtual async Task RenderViewComponentToStringAsync(Type componentType, object arguments = null)
    {
        var helper = new DefaultViewComponentHelper(
            EngineContext.Current.Resolve(),
            HtmlEncoder.Default,
            EngineContext.Current.Resolve(),
            EngineContext.Current.Resolve(),
            EngineContext.Current.Resolve());

        using var writer = new StringWriter();
        var context = new ViewContext(ControllerContext, NullView.Instance, ViewData, TempData, writer, new HtmlHelperOptions());
        helper.Contextualize(context);
        var result = await helper.InvokeAsync(componentType, arguments);
        result.WriteTo(writer, HtmlEncoder.Default);
        await writer.FlushAsync();
        return writer.ToString();
    }

    /// 
    /// Render partial view to string
    /// 
    /// View name
    /// Model
    /// 
    /// A task that represents the asynchronous operation
    /// The task result contains the result
    /// 
    protected virtual async Task RenderPartialViewToStringAsync(string viewName, object model)
    {
        //get Razor view engine
        var razorViewEngine = EngineContext.Current.Resolve();

        //create action context
        var actionContext = new ActionContext(HttpContext, RouteData, ControllerContext.ActionDescriptor, ModelState);

        //set view name as action name in case if not passed
        if (string.IsNullOrEmpty(viewName))
            viewName = ControllerContext.ActionDescriptor.ActionName;

        //partial view are not part of the controller life cycle.
        //hence, we could no use action filters to intercept the Models being returned
        //as we do in the /Nop.Web.Framework/Mvc/Filters/PublishModelEventsAttribute.cs for controllers
        switch (model)
        {
            case BaseNopModel nopModel:
            {
                var eventPublisher = EngineContext.Current.Resolve();

                //we publish the ModelPrepared event for all models as the BaseNopModel, 
                //so you need to implement IConsumer> interface to handle this event
                eventPublisher.ModelPreparedAsync(nopModel).Wait();
                break;
            }
            case IEnumerable modelCollection:
            {
                var eventPublisher = EngineContext.Current.Resolve();

                //we publish the ModelPrepared event for collection as the IEnumerable, 
                //so you need to implement IConsumer>> interface to handle this event
                eventPublisher.ModelPreparedAsync(modelCollection).Wait();
                break;
            }
        }

        //set model
        ViewData.Model = model;

        //try to get a view by the name
        var viewResult = razorViewEngine.FindView(actionContext, viewName, false);

        if (viewResult.View == null)
        {
            //or try to get a view by the path
            viewResult = razorViewEngine.GetView(null, viewName, false);
            if (viewResult.View == null)
                throw new ArgumentNullException($"{viewName} view was not found");
        }

        await using var stringWriter = new StringWriter();
        var viewContext = new ViewContext(actionContext, viewResult.View, ViewData, TempData, stringWriter, new HtmlHelperOptions());
        await viewResult.View.RenderAsync(viewContext);

        return stringWriter.GetStringBuilder().ToString();
    }

    #endregion

    #region Notifications

    /// 
    /// Error's JSON data
    /// 
    /// Error text
    /// Error's JSON data
    protected JsonResult ErrorJson(string error)
    {
        return Json(new
        {
            error
        });
    }

    /// 
    /// Error's JSON data
    /// 
    /// Error messages
    /// Error's JSON data
    protected JsonResult ErrorJson(object errors)
    {
        return Json(new
        {
            error = errors
        });
    }
    /// 
    /// Display "Edit" (manage) link (in public store)
    /// 
    /// Edit page URL
    protected virtual void DisplayEditLink(string editPageUrl)
    {
        var nopHtmlHelper = EngineContext.Current.Resolve();

        nopHtmlHelper.AddEditPageUrl(editPageUrl);
    }

    #endregion

    #region Localization

    /// 
    /// Add locales for localizable entities
    /// 
    /// Localizable model
    /// Language service
    /// Locales
    protected virtual async Task AddLocalesAsync(ILanguageService languageService,
        IList locales) where TLocalizedModelLocal : ILocalizedLocaleModel
    {
        await AddLocalesAsync(languageService, locales, null);
    }

    /// 
    /// Add locales for localizable entities
    /// 
    /// Localizable model
    /// Language service
    /// Locales
    /// Configure action
    protected virtual async Task AddLocalesAsync(ILanguageService languageService,
        IList locales, Action configure) where TLocalizedModelLocal : ILocalizedLocaleModel
    {
        foreach (var language in await languageService.GetAllLanguagesAsync(true))
        {
            var locale = Activator.CreateInstance();
            locale.LanguageId = language.Id;

            configure?.Invoke(locale, locale.LanguageId);

            locales.Add(locale);
        }
    }


    #endregion

    #region Security

    /// 
    /// Access denied view
    /// 
    /// Access denied view
    protected virtual IActionResult AccessDeniedView()
    {
        var webHelper = EngineContext.Current.Resolve();

        //return Challenge();
        return RedirectToAction("AccessDenied", "Security", new { pageUrl = webHelper.GetRawUrl(Request) });
    }

    /// 
    /// Access denied JSON data for DataTables
    /// 
    /// 
    /// A task that represents the asynchronous operation
    /// The task result contains the access denied JSON data
    /// 
    protected virtual async Task AccessDeniedDataTablesJson()
    {
        var localizationService = EngineContext.Current.Resolve();

        return ErrorJson(await localizationService.GetResourceAsync("Admin.AccessDenied.Description"));
    }

    #endregion

    #region Cards and tabs

    /// 
    /// Save selected card name
    /// 
    /// Card name to save
    /// A value indicating whether a message should be persisted for the next request. Pass null to ignore
    public virtual void SaveSelectedCardName(string cardName, bool persistForTheNextRequest = true)
    {
        //keep this method synchronized with
        //"GetSelectedCardName" method of \Nop.Web.Framework\Extensions\HtmlExtensions.cs
        ArgumentException.ThrowIfNullOrEmpty(cardName);

        const string dataKey = "nop.selected-card-name";
        if (persistForTheNextRequest)
        {
            TempData[dataKey] = cardName;
        }
        else
        {
            ViewData[dataKey] = cardName;
        }
    }

    /// 
    /// Save selected tab name
    /// 
    /// Tab name to save; empty to automatically detect it
    /// A value indicating whether a message should be persisted for the next request. Pass null to ignore
    public virtual async Task SaveSelectedTabNameAsync(string tabName = "", bool persistForTheNextRequest = true)
    {
        //default root tab
        SaveSelectedTabName(tabName, await Request.GetFormValueAsync("selected-tab-name"), null, persistForTheNextRequest);
        //child tabs (usually used for localization)
        //Form is available for POST only
        if (!Request.IsPostRequest() || !Request.HasFormContentType)
            return;

        var form = await Request.ReadFormAsync();

        foreach (var item in form)
            if (item.Key.StartsWith("selected-tab-name-", StringComparison.InvariantCultureIgnoreCase))
                SaveSelectedTabName(null, item.Value, item.Key["selected-tab-name-".Length..], persistForTheNextRequest);
    }

    /// 
    /// Save selected tab name
    /// 
    /// Tab name to save; empty to automatically detect it
    /// A value indicating whether a message should be persisted for the next request. Pass null to ignore
    /// Selected tab name
    /// A prefix for child tab to process
    protected virtual void SaveSelectedTabName(string tabName, StringValues selectedTabName, string dataKeyPrefix, bool persistForTheNextRequest)
    {
        //keep this method synchronized with
        //"GetSelectedTabName" method of \Nop.Web.Framework\Extensions\HtmlExtensions.cs
        if (string.IsNullOrEmpty(tabName))
            tabName = selectedTabName;

        if (string.IsNullOrEmpty(tabName))
            return;

        var dataKey = "nop.selected-tab-name";
        if (!string.IsNullOrEmpty(dataKeyPrefix))
            dataKey += $"-{dataKeyPrefix}";

        if (persistForTheNextRequest)
            TempData[dataKey] = tabName;
        else
            ViewData[dataKey] = tabName;
    }

    #endregion
}