Developer forum

Forum » Development » DWAPI: Pageviews fails

DWAPI: Pageviews fails

Anders Ebdrup
Anders Ebdrup
Reply

Hi Dynamicweb

 

We are working with the DWAPI here: http://rapido-342-full.websrv01.smartpage.dk/dwapi/docs/index.html?url=/dwapi/api.json&layout=BaseLayout#/PageViews/PageViews_GetById

But the frontpage (ID: 6279) is failing with this exception:

Object reference not set to an instance of an object.
   at Dynamicweb.Ecommerce.Frontend.Renderer.RenderCurrency(Currency currency, Template template, String tagName, Boolean checkForTag, RenderingContext renderingContext)
   at Dynamicweb.Ecommerce.Frontend.PageViewGlobalTagsSubscriber.OnNotify(String notification, NotificationArgs args)
   at Dynamicweb.Extensibility.Notifications.NotificationManager.Notify(String notification, NotificationArgs eventArgs)
   at Dynamicweb.Frontend.PageView.GetGlobalTemplateTags()
   at Dynamicweb.Rendering.RazorTemplateBase`1.GetGlobalValue(String name)
   at CompiledRazorTemplates.Dynamic.RazorEngine_fc730fc257144ff0a50015c25adaaa45.GetArticleCategoryColor(Int32 pageId) in F:\\Solutions\\Rapido 3.4.2 Full\\Files\\Templates\\Designs\\Rapido\\ItemPublisher\\List\\DynamicList.cshtml:line 47

 

Anything we should be aware of here?

 

Best regards, Anders


Replies

 
Olga Shedko Dynamicweb Employee
Olga Shedko
Reply

Hello Anders,

I've recently noticed this issue and created Bug 1520 for fixing it.

Thank you.

Best regards,

Olga | QA

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

Hi Anders

We will look into this one.

But - I do not think you should use a Rapido setup for this. By retrieving a pageview on a Rapido you also get a serialisation of the entire Area and it has very big item type with sub item types and lots of data. The error you see here is related to some missing context in a template in a regular rendering environment. And this will have some natural issues.

So in this case you try to render content as markup and return it to the json api - which does not really make a lot of sense I guess.

It can work though - see below:

 
Anders Ebdrup
Anders Ebdrup
Reply

Dear Nicolai,

 

If I try to request the pageview for: 6308, then it fails - se below:

 

at Dynamicweb.Ecommerce.Cart.CartSession.Add(String key, Object value)\r\n   at Dynamicweb.Ecommerce.Frontend.Cart.CartService.LoadCart(User user, OrderContext orderContext)\r\n   at Dynamicweb.Ecommerce.Common.Context.GetCart(OrderContext orderContext)\r\n   at Dynamicweb.Ecommerce.Frontend.Cart.CartCatch.CatchCart(Int32 pageId, PageView pageView)\r\n   at Dynamicweb.Ecommerce.Frontend.EcomPageLoadNotificationSubscriber.LoadedPage(PageView pageview)\r\n   at Dynamicweb.Extensibility.Notifications.NotificationManager.Notify(String notification, NotificationArgs eventArgs)\r\n   at Dynamicweb.Frontend.PageView.Load()\r\n   at Dynamicweb.Ecommerce.WebAPI.Controllers.PageViewsController.GetById(Int32 id)\r\n   at lambda_method(Closure , Object , Object[] )\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()

 

But am I missing something here?

 

Best regards, Anders

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

I get information that the page is not published...:

Again - you cannot use Rapido for this. There are too many things in Rapido that will not work in this context.

The webapi is session, cookie and stateless, and things in Rapido templates depend on that.

Getting pageviews also does not make a lot of sense in a headless environment (of course it should work though) as it will return rendered markup. And that markup comes from razor templates (which you are trying to avoid, I guess). And those templates use stuff that is not available in the web-api. I.e. things from HttpContext....

 
Martin Vang Dynamicweb Employee
Martin Vang
Reply

Hi Anders,

While I agree with Nicolai that it's a bit strange to request the json-hackpage that generates the data we need for the minicart, it does actually not fail for me (after I published the page).

I only added a single product to the cart here, but the data is present as I expected.

This is on the latest Rapido 3.4.3, fresh rapido 3.4.3 database and on our head branch. Can you show the entire stack-trace instead of just part of it? Would help me give you a suggestion besides "try without custom code" :)

BR

Martin

 
Anders Ebdrup
Anders Ebdrup
Reply

Dear Martin,

 

There is no custom code here - just plain Dynamicweb 9.10.5 and Rapido 3.4.2 without any customizations :-)

I agree about the cart that is should not be fetched through the Pageview-api, but for now we do not have a Cart-api in the webapi...

 

Best regards, Anders

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

The cart in 'regular' Dynamicweb is kept alive for a user given either a session, a cookie or a userid (and the the user id comes from a user login that is persisted in session)

Now - the webapi is stateless. It has no cookies, hence no sessions. So trying to fetch a page, using the pagview endpoint, and on that page have a paragraph with the cart module will result in an empty cart no matter what - because no user, no cookie or no session exists. So the page will see the cart as empty and do a redirect if it is setup to that, resulting in a 404.

In the context of the webapi, you can consider Rapido as a customisation. It has templates that renders stuff - in those templates there are all sorts of assumptions, i.e. there is a user or a cart, and since we have no sesssion and cookies, the templates will likely run into all kinds of errors due to this.

So - the webapi is not very suitable for getting a pageview where you use a regular page with rendering using templates. It will simply not work very well. Because part of the returning data will be rendered markup from templates that does not comply.

The Pageview in Dynamicweb is to be considered as the 'head' of Dynamicweb. Moving to the 'headless' version, using the webapi, using the pageview to partially render markup makes no sense.

What you will get from the pageview endpoint, when used in a headless-ish setup of your website structure, using items, is a page, its properties, its item data and its paragraphs. Right now those paragraphs comes as markup. In a very near future they will come as a collection of ParagraphViewModels using paragraph and item properties - like if you query them from the paragraphs endpoint.

Some paragraphs will have modules. Those modules comes in 2 flavors - those exposing the good old template tags and those exposing viewmodels. Those exposing viewmodels will at some point also be attached to the paragraph when we have the infrastructure for it (and the paragraphs is coming from the collection of paragraphs on a pageview).

The way of thinking an implementation in a headless environment using the webapis have to change some what compared to using pages with paragrapsh and modules as you do today.

Here is a number of things to consider and how they play out in the 2 environments

  Using Dynamicweb and templates Using the Webapi in a headless environment
Login Using a login form, a user logs in and Dynamicweb will send back a cookie and keep a session a live for some time. Whenever a new page is accessed, we find the user from session using the cookie as backup and ensures we have a user context. To get prices etc. Using a login form, the username and password is sent to the users endpoint to authenticate the user. A jwt token is returned as the response. The client has to store that token somehow - in a variable in the SPA, using cookies or localdb. At every subsequent request to the web api, the token is send in the auth header and the endpoint will then authorize based on that token. The token will expire and has to be renewed or the user will have to login again.
Cart When doing ?cartcmd=add Dynamicweb will, using the session, a cookie or the logged in user, find the appropiate cart or create one if missing. Then add the product as an orderline. On subsequent requests to pages, Dynamicweb will remember that and find the cart for displaying and additional cart actions Using the webapi, with no states, the client has to keep track of things. So to create a cart, the cart endpoint is called to explicitly create a cart. A cart token is returned and has to be stored in the client like with user above. On subsequent requests to the cart endpoint for adding and changing the cart, that cart token has to be passed along so the endpoint can find the appropiate cart.
Product catalog Using a page with a paragaph, the product catalog app is added and configured using the UI with how many products to show, where from etc. When that page is rendered, Dynamicweb will use those settings to find the right products, use the userid to find the right price, use the website context to locate the currency, delivery country, if prices are with vat and other funny stuff kept in the context (sesssion/cookie). All of this is rendered using a template setup on the app. Using the webapi, the product catalog has its own endpoint where products can be queried and a product listviewmodel is returned. There is no page and no paragraph. Also there is no settings coming from the app installed on the paragraph and there is no context of currency, user and other things. So those settings is send as part of the request. A groupid, a search string, what fields to return, what currency to use, what user (using the bearer token), if prices are with or without vat etc. The endpoint will return just raw data that needs to be rendered in the client
Forms Add forms to a paragraph, give it settings and a template will render the form. Submitting the form will take care of things and redirect to receipt We do not have this endpoint yet, but when it is, it will return a form object with fields and options, and that form has to be rendered in the client. The result of the form can be posted to the upcoming forms endpoint which will take care of things. The receipt has to be showed in the client and handled by the app it self.

 BR Nicolai

 

You must be logged in to post in the forum