Hi,
As a thought, did you create anything to render the page type (e.g. a controller)?
I noticed that blocks dont need a controller, so was tyring a page without a controller as I saw this approach on a few articles.
I did try creating a view in Views/HelloWorld/index.cshtml like this:
@model DxcAlloy.Models.Pages.HelloWorld
<div>
Hello!
</div>
But this did not help.
What should I put in a controller as bare minimum?
Inerestingly, when I right click on Controllers and select new item->Episerver, There is no page controller. only "block type", "block controller (MVC)", "Page Type" etc. A long list which is only missing "Page Controller (MVC)" or anything like it. Block controller is listed 4 times for some strange reason.
I manually created a class in Controllers called "HelloWorldController.cs" like this:
namespace DxcAlloy.Controllers
{
public class HelloWorldController:PageController<HelloWorld>
{
public ActionResult Index(HelloWorld currentPage)
{
return View(currentPage);
}
}
}
Now I get this:
The model item passed into the dictionary is of type 'Castle.Proxies.HelloWorldProxy', but this dictionary requires a model item of type 'DxcAlloy.Models.ViewModels.IPageViewModel`1[DxcAlloy.Models.Pages.SitePageData]'.
Hi,
In the alloy site there is a fallback controller setup which will act as the controller for pages which don't have a controller defined so that's probably why you've seen page types without a controller which render correctly in alloy. That fallback controller only kicks in for pages which inherit SitePageData though and your page inherits PageData instead hence it not being handled in the same way.
I suspect the issue you're seeing with the model type will be related to your layout file. The default layout in alloy expects a model of type IPageViewModel<SitePageData> and you're passing in just the HelloWorld page instance as a model. If you want to use the alloy layout file, you'll need to construct an instance if IPageViewModel in your controller and pass that as the model to your view. Bear in mind though that IPageViewModel also expects a page type which inherits from SitePageData which yours doesn't. The alternative, if you don't want to use the alloy layout file, is to specify the layout file in your view either as null to have no layout or pointed to a valid layout file which can handle a model of type HelloWorld.
The best option for you will depend on what you're trying to achieve but I'd generally recommend having a base type in your solution which your pages inherit (such as SitePageData in Alloy) and a viewmodel passed to your views rather than just the PageData object. In the case of the base type, that will allow you to set up common properties such as meta tags which all of your page types will need. Using a viewmodel rather than just the PageData allows you to pass additional data such as navigation alongside your page content which would otherwise need to be fetched elsewhere.
Thanks! how do I create a hello world layout? i.e. not use the default alloy one?
At it's most basic you could just create a cshtml file which looks something like this:
<!doctype html>
<html lang="en">
<head>
</head>
<body>
@RenderBody()
</body>
</html>
The important bit being the "@RenderBody()" as that's where the template markup gets inserted. You may also want to include the following line in there as it gives you the handy orange CMS navigation which appears when you're logged in to the CMS:
@Html.RenderEPiServerQuickNavigator()
Then, at the top of your actual view for your page, reference the layout you want to use like this:
@{
Layout = "~/Views/Path/To/My/Layouts/_MyLayout.cshtml";
}
Wouldn't it be easier to inherit SitePageData (not PageData) instead of creating a separate layout view?
Unless you actually want a different layout, of course.
I created a new HelloWorld page type in alloy, then edited Admin->content type to allow this new page to appear under the root page.
I create the page, and published it. The page has "Name in URL" of helloworld. So I am guessing the URL I should use to "see" the page is:
http://localhost:60746/helloworld
Where http://localhost:60746/ is the working local alloy site.
http://localhost:60746/helloworld gives me the IIS 404 page.
Detailed Error Information:
Module IIS Web Core
Notification MapRequestHandler
Handler StaticFile
Error Code 0x80070002
Requested URL http://localhost:60746/helloworld
Physical Path D:\dev\epi\DxcAlloy\helloworld
Logon Method ApplicationCookie
Logon User Alice
http://localhost:60746/en/helloworld gives me a .net error page: "Server Error in '/' Application. The resource cannot be found"
looking in App Data/EPiServerErrors.log, the only thing i see is the bellow error. If I search for "your_uri" in the project source, it doesnt find it.
2020-06-22 09:36:29,145 [16] ERROR EPiServer.Find.Cms.ContentEventIndexer: An exception occurred while indexing (IContent). The remote name could not be resolved: 'your_uri'.
System.Net.WebException: The remote name could not be resolved: 'your_uri'
at System.Net.HttpWebRequest.GetRequestStream(TransportContext& context)
at System.Net.HttpWebRequest.GetRequestStream()
at EPiServer.Find.Connection.JsonRequest.GetRequestStream(Int64 contentLength)
at EPiServer.Find.Json.Serializer.SerializeObjectsToJsonRequest(JsonSerializer serializer, IJsonRequest jsonRequest, IEnumerable values)
at EPiServer.Find.Api.BulkCommand.Execute(List`1& serializationFailures)
at EPiServer.Find.Api.BulkCommand.Execute()
at EPiServer.Find.Client.Index(IEnumerable objectsToIndex, Boolean deleteLanguageRoutingDuplicatesOnIndex)
at EPiServer.Find.Cms.ContentIndexer.IndexWithRetry(IContent[] contents, Int32 maxRetries, Boolean deleteLanguageRoutingDuplicatesOnIndex)
at EPiServer.Find.Cms.ContentIndexer.Index(IEnumerable`1 contents, IndexOptions options)
at EPiServer.Find.Cms.ContentEventIndexer.Index(IEnumerable`1 contentLinks)
at EPiServer.Find.Cms.ContentEventIndexer.<>c__DisplayClass25_0.<IndexPageQueue>b__0()
at EPiServer.Find.Cms.ContentEventIndexer.Sync(IEnumerable`1 contentToIndex, HashSet`1 contentToIndexSet, Func`1 index)
at EPiServer.Find.Cms.ContentEventIndexer.IndexPageQueue(IEnumerable`1 contentToIndex)
at EPiServer.Find.Cms.ContentEventIndexer.IndexPageQueue()
This is the page:
namespace DxcAlloy.Models.Pages
{
[ContentType(DisplayName = "HelloWorld", GUID = "5e4176f9-613d-4c9e-9c85-37dd1d1d70d9", Description = "")]
public class HelloWorld : PageData
{
[Display(
GroupName = SystemTabNames.Content,
Order = 10)]
public virtual ContentArea ItemLiistContentArea { get; set; }
}
}