Having a default RequestModel?

Hi we have a get “api”, that needs to get it general RequestModel from the domain, insted of the request context headers.
Its uses the ApiControllerBase and because of this the ActionFilter that builds the requestModel on the normal controllers is not run when the request hit the url.

So I came up with this rewrite of the RequestModelAccessor and wondering if there is a better way or if this seams like an ok solution? ge: Createing a own RequestModelImpl and building it if needed.

using System;
using System.Linq;
using System.Threading;
using Litium.Accelerator.Search;
using Litium.Foundation.Modules.ECommerce.ShoppingCarts;
using Litium.Globalization;
using Litium.Runtime.AutoMapper;
using Litium.Runtime.DependencyInjection;
using Litium.Web.Models.Globalization;
using Litium.Web.Models.Websites;
using Litium.Web.Routing;
using Litium.Websites;

namespace Litium.Accelerator.Routing
{
[Service(ServiceType = typeof(RequestModelAccessor))]
public class RequestModelAccessor
{
	private static readonly AsyncLocal<RequestModel> _routeRequest = new AsyncLocal<RequestModel>();

	public virtual RequestModel RequestModel
	{
		get
		{
			var context = System.Web.HttpContext.Current;
			if (context != null && context.Items.Contains(nameof(RequestModel)))
			{
				return (RequestModel)context.Items[nameof(RequestModel)];
			}

			//If we dont get a model, create a default
			if (_routeRequest.Value == null)
			{
				_routeRequest.Value = BuildDefaultRequestModel();
			}
			return _routeRequest.Value;
		}

		set
		{
			var context = System.Web.HttpContext.Current;
			if (context != null)
			{
				context.Items[nameof(RequestModel)] = value;
			}
			else
			{
				_routeRequest.Value = value;
			}
		}
	}

	//Hack to inject a basic request model if called before its created
	private RequestModelImpl BuildDefaultRequestModel(){

		RouteRequestLookupInfoAccessor routeRequestLookupInfoAccessor = IoC.Resolve<RouteRequestLookupInfoAccessor>();

		CartAccessor cartAccessor = IoC.Resolve<CartAccessor>();
		PageService pageService = IoC.Resolve<PageService>();

		Channel channel = routeRequestLookupInfoAccessor.RouteRequestLookupInfo.Channel;

		var rootPage = pageService.GetChildPages(Guid.Empty, channel.WebsiteSystemId).FirstOrDefault();

		return  new RequestModelImpl(cartAccessor)
		{
			_channelModel = new Lazy<ChannelModel>(() => channel.MapTo<ChannelModel>()),
			_searchQuery = new Lazy<SearchQuery>(() => new SearchQuery()),
			_currentPageModel = new Lazy<PageModel>(() => rootPage.MapTo<PageModel>()),
		};

	}
	private class RequestModelImpl : RequestModel
	{
		public Lazy<ChannelModel> _channelModel;
		public Lazy<SearchQuery> _searchQuery;
		public Lazy<PageModel> _currentPageModel;

		public RequestModelImpl(CartAccessor cartAccessor) : base(cartAccessor)
		{
		}

		public override ChannelModel ChannelModel => _channelModel?.Value;
		public override SearchQuery SearchQuery => _searchQuery?.Value;
		public override PageModel CurrentPageModel => _currentPageModel?.Value;
	}

}
}

Litium version: 7.4

In the default code for accelerator you have an RequestModelHandler that is registered in the pipeline for the ApiControllers. The RequestModelHandler is only setting the RequestModel is the extra header exists. Maybe you can modify that one the build your RequsetModel for the root page when the extra header not is included.

1 Like

The problem i face then is that RequestModelHandler is called on normal pages aswell, so there i have to add a check to see if its an api call or not so i dont override the normal flow, eg: I need to hardcode that lookup. But this seams like a good place to put the code so it might be a ok tradeoff thanks.

I just did:

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var siteSettingViewModel = request.Headers.GetSiteSettingViewModel(request);

		//If this is the site settings is null, we are probebly in a mock api call, then we pretend to be on the startpage
		if (siteSettingViewModel == null && IsApiRequest(request))
		{
			Channel channel = _routeRequestLookupInfoAccessor.RouteRequestLookupInfo.Channel;
			Page homePage = _pageService.GetChildPages(Guid.Empty, channel.WebsiteSystemId).FirstOrDefault();
			siteSettingViewModel = new SiteSettingViewModel() { ChannelSystemId = channel.SystemId, CurrentPageSystemId = homePage.SystemId, ProductCategorySystemId = null, CurrentVariantSystemId = null, CurrentBaseProductSystemId = null };
		}


          .........
    }

		private bool IsApiRequest(HttpRequestMessage request)
	{
		var req = request.RequestUri.PathAndQuery.ToLower();
		if (req.Contains("json") || req.Contains("api"))
		{
			return true;
		}

		return false;
	}

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.