SaaS CMS has officially launched! Learn more now.

PropertyFor MVC syntax for properties added by admin not by code.

Vote:
 

In MVC the 

@Html.PropertyFor(x => x.CurrentPage.TopMain) works just fine because the property TopMain has been added by code into the page type. 

Now go login as admin and add a property called "Test" to the same page type. 
@Html.PropertyFor(x => x.CurrentPage.Test)   Throws exception because Test is not part of the model. Makes sense. 

The question is, how can we support the new properties added by admin (not code) in MVC. 

It would be a useful feature because you don't need to build the solution in order to add new properties to the page types that way. 

Thanks,

Syed

#87488
Jun 13, 2014 23:35
Vote:
 

Sorry for a stupid question but why do you want to do that. Why not create all properties from code, you will need to add the viewsupport for the admin-added properies by coding anyway?

The only way I can think of to do this is to extend the PropertyFor and pass the property name in by something like @Html.PropertyFor(x=>x.CurrentPage, "Test") but I think it would take a lot of job to make it editible in the onpageedit.
But someone might have a better answer than me for you hopefully ;-)

#87493
Jun 16, 2014 7:42
Vote:
 

For "read-only" cases and "scalar" porperties you can output page property directly to markup with html out syntax:

<h1>@Model.CurrentPage["PageName"]</h1>

This will not support on page-edit, more complex property types - like ContentArea, etc. 

Properties from code is preferred way to work with EPiServer pages and data.

To extend PropertyFor with property name would be much of work as you need to make sure that templates are resolved correctly, that you support on-page edit and much more of gazillion features :)

#87501
Jun 16, 2014 9:54
Vote:
 

You have a good question Henrik. We want to create a few page types that a lot of our customers will use when implimenting EPI Server framework. Each page type will have specific properties already include. While most of the consumers will be happy with properties included, there will be a few cases where included properties are simply not enough to support the content types they have. 

What would be a best approach used here to offer extensibilty with minimum or no C# code to add new properties, forward compatibility in case we came with new version of the same tool etc. 

Thanks,

Syed

#87531
Jun 16, 2014 18:34
Vote:
 

Then I would guess best option could be to review PropertyFor code and extract needed parts (like template resolving), iterate througn "foreign" page properties (those added by customers themselves) and render those by looping through.

#87532
Jun 16, 2014 18:40
Vote:
 

I think you can go the way Valdis say, but I think it will take a lot of effort to do it. The most simple way is like Valdis said before, use the "old" syntax for them and not offer them onpagedit @Model.CurrentPage["PropertyName"]

#87533
Jun 16, 2014 20:31
Vote:
 

Since the ordinary PropertyFor looks like this:

    public static MvcHtmlString PropertyFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
    {
      string propertyName = PropertyExtensions.PropertyRenderer.GetPropertyName<TModel, TValue>(expression);
      return PropertyExtensions.PropertyRenderer.PropertyFor<TModel, TValue>(html, propertyName, (object) null, (object) null, expression, (Func<string, MvcHtmlString>) (templateName =>
      {
        if (!string.IsNullOrEmpty(templateName))
          return DisplayExtensions.DisplayFor<TModel, TValue>(html, expression, templateName);
        else
          return DisplayExtensions.DisplayFor<TModel, TValue>(html, expression);
      }));
    }

Note that the first line inside the method says "string propertyName = " and some functionality to determine the PropertyName based on the expression parameter.

Since you already know your PropertyName I would suggest that you create an extension method similar to:

    public static MvcHtmlString PropertyFor<TModel, TValue>(this HtmlHelper<TModel> html, string propertyName)
    {
      return PropertyExtensions.PropertyRenderer.PropertyFor<TModel, TValue>(html, propertyName, (object) null, (object) null, expression, (Func<string, MvcHtmlString>) (templateName =>
      {
        if (!string.IsNullOrEmpty(templateName))
          return DisplayExtensions.DisplayFor<TModel, TValue>(html, expression, templateName);
        else
          return DisplayExtensions.DisplayFor<TModel, TValue>(html, expression);
      }));
    }

You can take a look at the class EPiServer.Web.Mvc.Html.PropertyExtensions if you want to create the other overloads for PropertyFor.

#87544
Jun 17, 2014 8:59
Vote:
 

DisplayFor expects to have an expression that will return a property for which to render an input. As originally author does not have a strongly typed property - I bet this may fail.

#87545
Jun 17, 2014 9:01
Vote:
 

Since the DisplayFor require the expression, can we convert the property name to an expression on the fly? 

#87593
Jun 17, 2014 16:14
Vote:
 

I looked into the possibility of adding admin added properties when building Virtual Template System. The example below gets you close and gives you a property that renders and that you can edit on page:

<div @Html.EditAttributes("AdminAddedRichText")>
    @Html.DisplayFor(p => p.CurrentPage.Property["AdminAddedRichText"].Value)
</div>

<div @Html.EditAttributes("AdminAddedContentArea")>
    @Html.DisplayFor(p => p.CurrentPage.Property["AdminAddedContentArea"].Value)
</div>

I have tested it nearly works but the only issue is that edit mode does not update the value on page when the value in the property is changed. In this case publishing and/or switching to forms view works does refresh the view.

You can work around the not refreshing issue but forcing the page to fully refresh when the property changes by using the following code in your controller (you would still need to write some code to parse out the admin added properties rather than hard coding as shown in the example):

//Get hold of the full refresh property existing edit hints
var editHints = ViewData[ViewDataKeys.FullRefreshProperties] as IList<string>;
if (editHints == null)
{
    editHints = new List<string>();
}

//Add edit hints for the admin added propety names we need to refresh for 
//(will need parse out properties that have not been added through code rather than hard coding)
string[] additionalHints = new string[] { "AdminAddedRichText", "AdminAddedContentArea" };
editHints = editHints.Union(additionalHints).ToList();

//Replace the edit hint collection 
ViewData[ViewDataKeys.FullRefreshProperties] = editHints;

This leads to a slightly clunky experience for users as the page is forced to fully refresh whenever one of the admin added properties changes, but it does solve the original problem.

#87661
Edited, Jun 18, 2014 21:43
Vote:
 

Hm, interesting. Didn't know that @Html.DisplayFor(p => p.CurrentPage.Property["AdminAddedRichText"].Value) could work.

#87662
Jun 18, 2014 22:25
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.