Developer forum

Forum » Dynamicweb 9.0 Upgrade issues » context.customer is NULL in price provider

context.customer is NULL in price provider

Peter Leleulya
Peter Leleulya
Reply

Hi guys,

I had to rewrite some price providers due to obsolete methods.

I had to use the FindPrice with the PriceContext parameter.

But when I debug and get into the FindPrice method the value of Customer within the price context is NULL even when there is a current user logged in ...
I would have expected the price context current user to be the currently loggedin user, or is that a misinterpretation and do I have to do something to get it filled?

I now added a line and worked with that: var customer = context?.Customer ?? User.GetCurrentUser(PagePermissionLevels.Frontend);

Additional, within this method I need the product number to do my magic. In the obsolete method I have the product and all its properties.
In this new method for each call I have to first get the product by id and variantid to get its number ... doesn't feel right ...


Replies

 
Morten Bengtson Dynamicweb Employee
Morten Bengtson
Reply

Hi Peter,

The price context depends on the context ;-)

When rendering prices in the product catalog then PriceContext.Customer is the current user.
When rendering prices in the shopping cart then PriceContext.Customer is the user associated with the cart/order instance (Order.CustomerAccessUserId).

The reason for the difference is that an order might be processed in a context where the current user is not available or where the order customer is not the current user.
Your custom price provider might be called in these scenarios.

If User.GetCurrentUser(PagePermissionLevels.Frontend) works for you then go with that, but I would not recommend doing so.
Instead I would suggest that you ensure that the order has a correct user id and then PriceContext.Customer will contain the correct user when your price provider is called.

If you think that it is a bug then please share some more details about how to reproduce the issue and we can take a closer look.

/Morten

 
Peter Leleulya
Peter Leleulya
Reply

Hi morten, 

What order, I'm trying to get prices. Why would there be an order?
Or is there some context value I need to set?

 
Morten Bengtson Dynamicweb Employee
Morten Bengtson
Reply

A shopping cart (order) has lines with products and prices. When these prices are calculated the price providers are called with price context information from the cart (customer, country, etc.). If you don't use shopping carts (or other types of orders) in your website then I guess there will not be an order.

It would be very helpful if you could provide more information about when and where the issue occurs.
"when I debug and get into the FindPrice method the value of Customer within the price context is NULL even when there is a current user logged in"
What's the call stack at that point where the value of Customer is null? You can get that by calling System.Environment.StackTrace.ToString() in your price provider.

 
Peter Leleulya
Peter Leleulya
Reply

Hi Morten,

I found out it might have to do with our custom implementation of the product list.
Perhaps yu have a tip for me what to do.

I put a breakpoint in the FindPrice method again and found out that when I log in and get the user assortment (custom) I break having the user set in the price context correctly.
Then when I navigate to the product list page I break having the user to be NULL in the price context.
I pasted the stack from that moment below.
When I navigate to a product detail page I break having the user set in the price context correctly.
When I add to cart and go to the cart I break having the user set in the price context correctly.
When I went to a product list again I break having the user to be NULL again in the price context.

The product list page has a paragraph with a Product Catalog for ViewModel APP placed on it, all properties set to "Include all" for the moment.
But in the list view template we do some magic.
We pass the model to a method which returns a custom extended model, but it doesn't hit the FindPrice there!
When the template uses the extended model values to show the products and wants to show a price I break having the user to be NULL in the price context.
The object we iterate through is a List<MasterWithVariantsModel>
MasterWithVariantsModel is some master data, List<Dynamicweb.Ecommerce.Produts.Product> and some other lists
The list of Product is printed in the template along with data from the other lists.

Can you come up with any reason why the user would be NULL?

Stack:

   at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
   at System.Environment.get_StackTrace()
   at MyProject.Application.CustomCode.Providers.SapPriceProvider.FindPrice(PriceContext context, PriceProductSelection selection) in C:\Projects_GIT\MyProject\MyProject.Application\CustomCode\Providers\SapPriceProvider.cs:line 40
   at Dynamicweb.Ecommerce.Prices.PriceManager.FindPriceInternal(PriceProvider provider, PriceContext context, PriceProductSelection selection, Boolean isInformative)
   at Dynamicweb.Ecommerce.Prices.PriceManager.FindPrice(PriceContext context, PriceProductSelection selection, Boolean isInformative)
   at Dynamicweb.Ecommerce.Prices.PriceManager.GetPrice(PriceContext context, Product product, String unitId, Int64 stockLocationId)
   at Dynamicweb.Ecommerce.Prices.PriceManager.GetPrice(Product product, String currencyCode, String countryCode, String unitId, Int32 userId, String shopId, StockLocation stockLocation)
   at Dynamicweb.Ecommerce.Products.Product.get_Price()
   at CompiledRazorTemplates.Dynamic.RazorEngine_4ee06cad6eb44079b90bdfc6279bcc7d.Execute() in C:\Projects_GIT\MyProject\MyProject.Application\Files\Templates\Designs\MyProject\eCom\ProductCatalog\ProductViewListFacets.cshtml:line 218
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader)
   at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
   at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()
   at Dynamicweb.Rendering.Template.Output()
   at Dynamicweb.Ecommerce.ProductCatalog.ProductCatalogFrontend.RenderProductList(ProductCatalogSettings settings, String groupId, Boolean feed)
   at Dynamicweb.Ecommerce.ProductCatalog.ProductCatalogFrontend.GetContent()
   at Dynamicweb.Frontend.Content.GetModuleOutput(Paragraph paragraph, PageView pageview)
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at CompiledRazorTemplates.Dynamic.RazorEngine_fdfe45703b2e4dcea800102ea60d653b.Execute() in C:\Projects_GIT\MyProject\MyProject.Application\Files\Templates\Designs\MyProject\Paragraph\ModuleOnly.cshtml:line 2
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader)
   at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
   at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()
   at Dynamicweb.Rendering.Template.Output()
   at Dynamicweb.Frontend.Content.RenderParagraph(Paragraph paragraph, ContainerInfo containerInfo, Layout layout, GridColumnViewModel column)
   at Dynamicweb.Frontend.Content.CreateContent(IList`1 paragraphs)
   at Dynamicweb.Frontend.Content.CreateContent(Int32 contentId)
   at Dynamicweb.Frontend.ContentViewModelFactory.CreatePageViewModel(PageView pageView)
   at Dynamicweb.Frontend.PageView.SetPageTemplateValues()
   at Dynamicweb.Frontend.PageView.Output()
   at Dynamicweb.AspNet.DynamicwebHttpHandler.ProcessRequest(HttpContext context)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step)
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
   at System.Web.HttpApplication.PipelineStepManager.ResumeSteps(Exception error)
   at System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb)
   at System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
   at System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr pHandler, RequestNotificationStatus& notificationStatus)
   at System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr pHandler, RequestNotificationStatus& notificationStatus)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)

 

 

 
Peter Leleulya
Peter Leleulya
Reply

Hi Morten,

I found out it might have to do with our custom implementation of the product list.
Perhaps yu have a tip for me what to do.

I put a breakpoint in the FindPrice method again and found out that when I log in and get the user assortment (custom) I break having the user set in the price context correctly.
Then when I navigate to the product list page I break having the user to be NULL in the price context.
I pasted the stack from that moment below.
When I navigate to a product detail page I break having the user set in the price context correctly.
When I add to cart and go to the cart I break having the user set in the price context correctly.
When I went to a product list again I break having the user to be NULL again in the price context.

The product list page has a paragraph with a Product Catalog for ViewModel APP placed on it, all properties set to "Include all" for the moment.
But in the list view template we do some magic.
We pass the model to a method which returns a custom extended model, but it doesn't hit the FindPrice there!
When the template uses the extended model values to show the products and wants to show a price I break having the user to be NULL in the price context.
The object we iterate through is a List<MasterWithVariantsModel>
MasterWithVariantsModel is some master data, List<Dynamicweb.Ecommerce.Produts.Product> and some other lists
The list of Product is printed in the template along with data from the other lists.

Can you come up with any reason why the user would be NULL?

Stack:

   at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
   at System.Environment.get_StackTrace()
   at MyProject.Application.CustomCode.Providers.SapPriceProvider.FindPrice(PriceContext context, PriceProductSelection selection) in C:\Projects_GIT\MyProject\MyProject.Application\CustomCode\Providers\SapPriceProvider.cs:line 40
   at Dynamicweb.Ecommerce.Prices.PriceManager.FindPriceInternal(PriceProvider provider, PriceContext context, PriceProductSelection selection, Boolean isInformative)
   at Dynamicweb.Ecommerce.Prices.PriceManager.FindPrice(PriceContext context, PriceProductSelection selection, Boolean isInformative)
   at Dynamicweb.Ecommerce.Prices.PriceManager.GetPrice(PriceContext context, Product product, String unitId, Int64 stockLocationId)
   at Dynamicweb.Ecommerce.Prices.PriceManager.GetPrice(Product product, String currencyCode, String countryCode, String unitId, Int32 userId, String shopId, StockLocation stockLocation)
   at Dynamicweb.Ecommerce.Products.Product.get_Price()
   at CompiledRazorTemplates.Dynamic.RazorEngine_4ee06cad6eb44079b90bdfc6279bcc7d.Execute() in C:\Projects_GIT\MyProject\MyProject.Application\Files\Templates\Designs\MyProject\eCom\ProductCatalog\ProductViewListFacets.cshtml:line 218
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader)
   at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
   at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()
   at Dynamicweb.Rendering.Template.Output()
   at Dynamicweb.Ecommerce.ProductCatalog.ProductCatalogFrontend.RenderProductList(ProductCatalogSettings settings, String groupId, Boolean feed)
   at Dynamicweb.Ecommerce.ProductCatalog.ProductCatalogFrontend.GetContent()
   at Dynamicweb.Frontend.Content.GetModuleOutput(Paragraph paragraph, PageView pageview)
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at CompiledRazorTemplates.Dynamic.RazorEngine_fdfe45703b2e4dcea800102ea60d653b.Execute() in C:\Projects_GIT\MyProject\MyProject.Application\Files\Templates\Designs\MyProject\Paragraph\ModuleOnly.cshtml:line 2
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader)
   at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
   at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()
   at Dynamicweb.Rendering.Template.Output()
   at Dynamicweb.Frontend.Content.RenderParagraph(Paragraph paragraph, ContainerInfo containerInfo, Layout layout, GridColumnViewModel column)
   at Dynamicweb.Frontend.Content.CreateContent(IList`1 paragraphs)
   at Dynamicweb.Frontend.Content.CreateContent(Int32 contentId)
   at Dynamicweb.Frontend.ContentViewModelFactory.CreatePageViewModel(PageView pageView)
   at Dynamicweb.Frontend.PageView.SetPageTemplateValues()
   at Dynamicweb.Frontend.PageView.Output()
   at Dynamicweb.AspNet.DynamicwebHttpHandler.ProcessRequest(HttpContext context)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step)
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
   at System.Web.HttpApplication.PipelineStepManager.ResumeSteps(Exception error)
   at System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb)
   at System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
   at System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr pHandler, RequestNotificationStatus& notificationStatus)
   at System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr pHandler, RequestNotificationStatus& notificationStatus)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)

 

 

 
Peter Leleulya
Peter Leleulya
Reply

This page crashed when adding my comment, ending up to be added twice ... sorry for that.

 
Morten Bengtson Dynamicweb Employee
Morten Bengtson
Reply
This post has been marked as an answer

Hi Peter,

Thanks for the details. It was very helpful.

I have found the cause of the problem and will try to figure out how to fix that.
Until then you can make a small change in the template to get the correct price...

The best solution would be to use the ProductViewModel.Price property, if possible...

foreach(ProductViewModel product in Model.Products)
{
    PriceViewModel price = product.Price;
}

Otherwise, you can replace the call to product.Price with this:

PriceInfo price = Dynamicweb.Ecommerce.Prices.PriceManager.GetPrice(product, Common.Context.Currency.Code, Common.Context.Country.Code2, User.GetCurrentExtranetUserId());

... or if you prefer using something that is not marked as obsolete...

PriceContext priceContext = new PriceContext(Common.Context.Currency, Common.Context.Country, Services.Shops.GetShop(Pageview.Area.EcomShopId), User.GetCurrentExtranetUser(), Common.Context.ReverseChargeForVatEnabled, Common.Context.OrderTime);
PriceInfo price = product.GetPrice(priceContext);

I know, neither of these last two solutions are pretty, but it's the best I can come up with right now. Sorry about that.
We'll try to figure out a better way to handle this.

Best regards,
Morten

Votes for this answer: 1
 
Peter Leleulya
Peter Leleulya
Reply

Hi Morten,

Thanks for your response.

 
Martin Moen
Reply

Quick question related to this. I tried your code.

PriceContext priceContext = new PriceContext(Common.Context.Currency, Common.Context.Country, Services.Shops.GetShop(Pageview.Area.EcomShopId), User.GetCurrentExtranetUser(), Common.Context.ReverseChargeForVatEnabled, Common.Context.OrderTime);
PriceInfo price = product.GetPrice(priceContext);

Im trying to get prices from BC through the live integration.
This code do get the price from BC, but even though im sending a different user in the PriceContext I still get the price for the logged in user, or if not logged in I get the price for the anonymous user.

I was hpoing I could override this, and be able to get a live price from BC on any customer through setting a different user in the price context. But it does not look like the user I set in the price context are used at all through the live integration.

Can you confirm that this is by purpose? I'm using DW 9.13.2.

 
Morten Bengtson Dynamicweb Employee
Morten Bengtson
Reply

Hi Martin,

It should work, but I can check if there is an issue with how our live integration handles this.

However, if you need to see products, prices, discounts, etc. as a different user then you should consider using impersonation instead.

Best regards,
Morten

 
Nicolai Pedersen
Reply

I think the price provider in live integration does still not use the price context - it has not been updated to use that yet. So there is still a lot of code that users GetCurrentExtranetUser that will basically overrule what you set on the price context....

 
Martin Moen
Reply
Thanks Morten. Is it possible to do impersonation through the API too? Do you have any quick examples?

 

You must be logged in to post in the forum