kontent-ai / boilerplate-net Goto Github PK
View Code? Open in Web Editor NEWKontent.ai Boilerplate for development of ASP.NET Core MVC applications.
Home Page: https://kontent.ai/
License: MIT License
Kontent.ai Boilerplate for development of ASP.NET Core MVC applications.
Home Page: https://kontent.ai/
License: MIT License
I have two objects 'Object1' and 'Object2'. 'Object2' is a child of 'Object1' (according to the CMS structure) and I have created a custom method that gets the correct URL path of the current page by it's codename - i.e. "/{object1Url}/{currentPageUrl}" or "/{object1Url}/{object2Url}/{currentPageUrl}".
I first check to see if the current page is of type 'Object1' by using the following request:
IDeliveryItemResponse<Object1> object1Response = _deliveryClient.GetItemAsync<Object1>(codename, new EqualsFilter("system.type", Object1.Codename), new ElementsParameter(Object1.Field1Codename, Object1.Field2Codename)).Result;
If this object is null, I know that the current page is a child of 'Object1'. So, I then check for 'Object2' by the codename, using the following:
IDeliveryItemResponse<Object2> object2Response = _deliveryClient.GetItemAsync<Object2>(codename, new EqualsFilter("system.type", Object2.Codename), new ElementsParameter(Object2.Field1Codename, Object2.Field2Codename)).Result;
I am then calling this custom method in two separate places and get two different results for the same codename (Content Item). In one of the place I am getting the correct result. But, in the second place, I am getting the Content Item of type 'Object2' returned in the 'object1Response' object, where I check to see if it is of type 'Object1'. So, the URL I build is incorrect for the type of page it is.
This only seems to happen when the current page is a child of the 'Object2' section - i.e. "/{object1Url}/{object2Url}/{currentPageUrl}". The codename I'm passing into the method is definitely for a Content Item of type 'Object2' - I have check this a couple time and also had a colleague double check.
Has anyone come across this as well and have any ways around it?
In spite of being just a dot release, the 2.1 brings many updates and performance improvements.
Upgrade according to references below. Rewrite code that's deprecated by MS.
setting up caching #26
domain redirect #27
robots
sitemap
link resolver #25
by @matodanko from #28 :
Regarding - Configs for Dev and Production environment
What's the recommended approach to setup environment for development, etc. It would be great to know more details about that, what's the best practice and how boilerplate could help in this manner.
Kentico Cloud now supports so called content type snippets. These are sets of content elements that can be added to content types to enrich their structure.
They allow you to add several content elements that are managed in one single place, similarly to how inheritance in object oriented programming works. You can add one snippet to a content type. Snippets cannot be added to other snippets, only to content types. The Delivery API responses contain both the elements originating from snippets alongside their own elements. The only difference in them is that elements from snippets have code names prefixed with the code name of the respective snippet. The format of code names is [code name of snippet]__[code name of element]
.
A shortened example of a content item:
{
"item": {
"system": {
// ...
"type": "brewer",
// ...
},
"elements": {
// ...
"product_name": {
"type": "text",
"name": "Product name",
"value": "AeroPress"
},
// ...
"metadata__meta_title": {
"type": "text",
"name": "Meta title",
"value": null
},
// ...
}
},
"modular_content": {}
}
Implement support for rendering content items of content types that utilize a content snippet.
A temporary Dancing Goat project with a preview of snippets is available for everyone who wants to participate in this effort. If you're interested in either adjusting the sample content or implementing the support in the app, let @JanLenoch know and you'll be given access to that project in Kentico Cloud.
The implementation should be in line with how the code generatorworks.
Currently, this issue is blocked by kontent-ai/model-generator-net#43 . But, the models of this app could be modified manually to overcome the block.
As it makes sense to support distributed caching along with the existing support of in-memory caching, we'd like to select the most suitable 3rd party caching library to do the job.
Ideally, the library should:
Note: Rewritten from #52 .
Use DeliveryOptions that's available in Delivery SDK. It can be used together with IOptions to quickly load environment variables.
This will also resolve #19
Probably AppVeyor + badge into README
Simple fixed-time caching - Could you please provide more details about this functionality?
How it works, when people should use it/should not, what's the best practice for caching in general.
More info: https://blogs.msdn.microsoft.com/dotnet/2017/02/07/announcing-net-core-tools-updates-in-vs-2017-rc/
Tooling: https://www.microsoft.com/net/core#windowscmd
We'll be probably able to get rid of the https://github.com/Kentico/cloud-boilerplate-net/blob/master/RenameProject.ps1 file.
Wiki: https://github.com/dotnet/templating/wiki/%22Runnable-Project%22-Templates
Existing templates: https://github.com/dotnet/templating/wiki/Available-templates-for-dotnet-new
Example installation: https://blogs.msdn.microsoft.com/webdev/2017/02/14/building-single-page-applications-on-asp-net-core-with-javascriptservices/
http://dotnetthoughts.net/create-a-dot-net-new-project-template-in-dot-net-core/
KenticoCloud Delivery SDK has significant breaking changes in version 8, so code based on this boiler plate cannot be updated to version 8, needing it to stay with version 6.
Besides the dotnet new
way of starting a new project, developers would welcome starting it in Visual Studio with File
-> New
-> Project
-> Kentico Cloud Web Application
.
All of the projects above support both dotnet new
and VSIX.
Other resources regarding the new templating engine:
Wiki: https://github.com/dotnet/templating/wiki/%22Runnable-Project%22-Templates
Existing templates: https://github.com/dotnet/templating/wiki/Available-templates-for-dotnet-new
http://dotnetthoughts.net/create-a-dot-net-new-project-template-in-dot-net-core/
The current boilerplate project is used to start a new web site on Kentico (users are instructed to do so). As such, users get the than-current code at the time of creating a new web site project. All fixes and improvements you made after that moment are usually missed and they never reach production for already existing web sites.
The boilerplate project contains two parts with different usage scenarios:
I would like to see the encapsulating code to be published as a somehow-officially-supported NuGet package.
It will have several benefits:
It will also have few expectations:
I did the split for my private projects as it makes no sense to maintain the same library code in several projects so it is feasible.
Trying to get the caching to work so that when an item is Published or Unpublished, the cache is cleared straight away on the Live site.
I have noticed within the InvalidatingCacheManager.cs object, there is an if condition checking if the value object is an AbstractResponse object and that the value has the 'HasStaleContent' property set to true (line 54 - attached screenshot below). But, when debugging this functionality, the 'HasStaleContent' value is also returning false.
I was expected this value to be true when an item has been Published or Unpublished.
I have recently upgraded a site to the latest version on this boilerplate. After the initial build of the site I noticed that most of the pages are missing sections. This is because the response from the API calls, return any linked item objects as null. When debugging I can see that the correct values are in the JSON response.
I am using the following to get the Project Individual Article:
The following is what is returned for the ContentModules object (The correct amount of items but all null). This should be a collection of type object as different content types can be used in this section:
This functionality was working fine before I upgraded tho the latest version on the boilerplate but can't see why this wouldn't work now. Has there been any changes been made that would stop this from working, that I have missed?
Any help would be much appreciated.
This project should be updated to .NET 8 and the latest nugets.
There are breaking changes that this project does not address such as this: kontent-ai/delivery-sdk-net#390
Update solution to .NET 8 and latest nugets.
Readme.md says it includes a robots.txt, but it does not.
Add the robots.txt
The HtmlHelperExtensions.AssetImage
method builds an img
tag which than renders as
<img โฆ></img>
The img
tag is a void element. So it should be rendered as just <img>
(HTML5, HTML) or self-closed <img/>
(HTML5, XHTML).
I suggest to add one of the following lines just before the return image;
statement to fix this.
image.TagRenderMode = TagRenderMode.SelfClosing; // XHTML-like <img/>
image.TagRenderMode = TagRenderMode.StartTag; // HTML-like <img>
When the CloudBoilerplateNet.ProjectOptions.KenticoCloudPreviewApiKey property is set, then all requests to the REST endpoints are being done with the Preview API key. The app should allow the developer to configure the Preview API key without forcing the app to actually use it.
With an ngrok url setup and the webhook url set to "webhooks/webhooks/index," I put a breakpoint on the Webhooks controller to follow the code - when it arrives at the "request.Body.Position=0" at line 26, it throws a "System.NotSupportedException" - the alternate Seek() method threw the same exception. When I commented out line 26, the system told me to change ReadToEnd() to async methods, but I ran into the same issues there. Kentico support suggested I open an issue for this.
What went wrong?
Webhook crashes on receiving a new message
Step through code in SignatureActionFilter, starting with line 26
KC has content personalization capabilities. By either placing a predefined JS code into web pages or by using the Tracking API (where JS cannot be used, e.g. native apps), one can start gathering information about visitors, converting them into contacts (after an email address was submitted via any form) and adding them to visitor segments (based on custom rules). Then, a web app may decide which content to render, based on a segment of a particular visitor. The only things needed are adding the JS code, adding the Personalization SDK NuGet package and having some decision logic that operates on the segment information.
Workflow related events cannot be deserialized into WebhookModel making the webhook controller action Index not executed since the model is null
Cause the following event to be sent to the webhook:
{
"data": {
"items": [
{
"item": {
"id": "76e78624-c7d7-53ae-ab0f-64dfde05e65e"
},
"language": {
"id": "00000000-0000-0000-0000-000000000000"
},
"transition_from": {
"id": "0041a1b3-1820-44d6-bd8a-f252f8f8bf6a"
},
"transition_to": {
"id": "61f60ea5-66e6-4b1e-9c8e-c34e0782f90f"
}
}
]
},
"message": {
"id": "960a79fc-95b3-42c0-96e3-1493bf6c0193",
"project_id": "ad8d8eda-c21e-000c-a5e6-7478633c60f3",
"type": "content_item_variant",
"operation": "change_workflow_step",
"api_name": "content_management",
"created_timestamp": "2019-12-21T00:35:36.2477126Z",
"webhook_url": "http://2a5a4d10.ngrok.io/webHooks/KenticoKontentWebHook"
}
}
There should be support for both type of events either by handling it in different actions or by some other means so both event model to be deserialized by the same action.
Proposed solution:
IDeliveryClient
)
So far it's not fully implemented in asp.net core 1.1, but it's implemented in asp.net core 1.2 that should be released in Q2/2017 (source). Once released, we should update boilerplate and add support for fully implemented support for IISUrlRewrite.xml
file format.
It will allow our users to use rewrite maps (i.g.: static redirects - old url -> new url).
<rewrite>
<rewriteMaps>
<!-- TODO: not supported yet, waiting for asp.net core 1.2 release -->
<!-- Example of 301 - Permanent redirect with old -> new URL mapping -->
<rewriteMap name="Static rewrites" defaultValue="">
<add key="/old-url" value="/?new-url=1" />
</rewriteMap>
</rewriteMaps>
</rewrite>
Currently, they have to use workaround or own solution.
The dotnet new
templates can be made parametrizable. Supplying a parameter value saves manual work needed when the template has been instantiated.
We can think of at least these two potential parameters:
example.com
in IISUrlRewrite.xml and robots.txtIf we eventually add code with integrations into this boilerplate and if we split the boilerplate into smaller projects with their NuGet packages, we might also allow the developer to list parts that they want to be in the form of a NuGet package (instead of raw code) right from the start (when starting a new project). One such integration would be the Personalization SDK.
Let's help developers keep their models in-sync with Kentico Kontent content models.
Run the code generator as a pre-build event target.
Target
in order for the build to consider the generated files (pre-build event doesn't work for the first build - e.g. petrsvihlik/StartBootstrap.Freelancer.Blazor@a9550ea)@KenticoBSoltis @JanLenoch can one of you please pick it up? thx
Ideally through some DI mechanism.
We'd like to have a functionality that would generate top-level navigation based on sitemap data in Kentico Cloud.
https://kenticocloud.com/blog/managing-navigation-menus-in-kentico-cloud
Similarly to #3, the issue is blocked by the capabilities of the sitemap endpoint.
In an early release of the boilerplate I could use the CachedDeliveryClient's GetItemAsync
method without any parameters:
var response = await DeliverClient.GetItemAsync<FullWidthContentPage>(PageCodeName);
I updated to the latest release code as of yesterday, and now I receive an error on that line: "parameter cannot be null". To get around it I was able to pass in an empty List but that was the only way I could get it to work. Like so:
var response = await DeliverClient.GetItemAsync<FullWidthContentPage>(PageCodeName, new List<IQueryParameter>());
I believe the issue is in how the code is written in KenticoCloudCacheHelper.cs
for the GetIdentifiersFromParameters
method, but I am not 100%.
I'm hoping someone can validate my findings, or tell me if I am wrong?
Middleware was designed by MS to run for all requests, without the notion of routing or other context of MVC.
Conversely, action filters are designed to run for specific controllers/actions.
Given that the webhook secret will never be used throughout the whole app, the rewrite of the SignatureActionFilter class into a middleware makes no sense. The conversion causes that on each and every hit to all controller actions, the request stream is being read and the hash is being calculated, over and over without a use.
Revert back to an action filter.
Blocks #93
There are several cache manager libraries in the wild. One of the nice ones is https://github.com/MichaCo/CacheManager . It supports various caching technologies (incl. distributed ones) and is designed to store various types of data in the cache (not only Kentico Cloud data).
Would you welcome such a generic cache manager in our boilerplate?
Pros:
Cons:
Pros and cons (at the same time):
Adjust the part for generating models:
<websitename>.Models
, while the utility generates KenticoCloudModels
by defaultAccording to the webhook debug, new requests sometimes end up with a 404 error. The webhook endpoint is configured on ~/webhooks/webhooks. The 404 status sometimes switches to 200 after some time for already performed webhooks
All requests return 200 unless the server is unavailable. Never get 404.
The Event log of the webhook endpoint show following stack trace:
System.InvalidOperationException: Unable to resolve service for type 'NoahMedia.Caching.Webhooks.ICacheManager' while attempting to activate 'NoahMedia.Areas.WebHooks.Controllers.WebhooksController'.
at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
at lambda_method(Closure , IServiceProvider , Object[] )
at Microsoft.AspNetCore.Mvc.Controllers.ControllerActivatorProvider.<>c__DisplayClass4_0.<CreateActivator>b__0(ControllerContext controllerContext)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at NoahMedia.Middleware.SignatureMiddleware.InvokeAsync(HttpContext httpContext, IOptions`1 projectOptions) in C:\Development\Noah\noah-media-group-kentico-cloud-main-website\Middleware\SignatureMiddleware.cs:line 39
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task
All details and maybe other beneficial info can be found in conversation 26023165963 and 26078540426.
I tried to install boilerplate from sources (https://github.com/Kentico/kontent-boilerplate-net/wiki/Installation-from-source), but this ended with error, that there are no artifacts.
You can see the problem in attached console output log boilerplate_from_sources.log
I would expect, that artifacts can be installed.
MS Windows 10
.Net version 5.0.203
Regarding - Configs for Dev and Production environment
What's the recommended approach to setup environment for development, etc. It would be great to know more details about that, what's the best practice and how boilerplate could help in this manner.
The 0.14.0 aspnet core extensions deprecated the traditional webhooks.
However, this boiler plate does not have an implementation that uses the new webhook infrastructure.
This boiler plate should be updated.
See here for breaking change:
(https://github.com/kontent-ai/aspnetcore-extensions/releases/tag/0.14.0)
Update this template to use the new webhook functionality.
The current Kentico Kontent .NET Core boilerplate only supports .NET Core 2.1. Some of our systems may have limitations for versions of .NET Core under version 3.0 (.NET Core 3.0 added some connectivity functionality for a legacy database system that we use), so an upgrade to .NET Core 3.0 would make using Kentico Kontent simpler in our case. Plus it would keep it in line with our current development plans to implement .NET Core 3.0.
We'd like to include a default robots.txt file.
Redesign the caching mechanism so that it is capable of purging select cached content based on HTTP messages sent from Kentico Cloud to the app's web hook endpoint.
PoC implementation: https://github.com/Kentico/cloud-example-webhook-cache-invalidation
TODOs:
Publishing a new version of an item and a corresponding webhook is being received with status code 200. This however leaves the live site still showing the old version of that item.
It seems to be a cache issue as it doesn't get updated with the webhook.
The cache would get updated and the live site would show the new version of the item.
Add any other context about the problem here.
Add links to screenshots, if possible.
For smoother developer experience.
Once /sitemap
delivery endpoint is available, we can start generating sitemap.xml automatically.
Currently, the CachedDeliveryClient references protected DeliveryClient DeliveryClient { get; }
which is wrong. It should reference IDeliveryClient
.
IDeliveryClient
in the constructorDeliveryClient
should be created outside the CachedDeliveryClient
public HttpClient HttpClient
will no longer be necessary in the CachedDeliveryClient
HttpClient
and pass it to an instance of the DeliveryClient
which will be passed to CachedDeliveryClient
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.