Abstract base class for View Models for Entities.
Inheritance: ViewModel, IRichTextFragment, IEntity
        public void BuildEntityModel(ref EntityModel entityModel, IComponentPresentation cp, Localization localization)
        {
            using (new Tracer(entityModel, cp, localization))
            {
                IFieldSet contextExpressionsFieldSet;
                if (cp.ExtensionData == null || !cp.ExtensionData.TryGetValue(Constants.ContextExpressionsKey, out contextExpressionsFieldSet))
                {
                    // No Context Expressions found; nothing to do.
                    return;
                }

                ContextExpressionConditions conditions = new ContextExpressionConditions();
                IField includeField;
                if (contextExpressionsFieldSet.TryGetValue("Include", out includeField))
                {
                    conditions.Include = includeField.Values.ToArray();
                }
                IField excludeField;
                if (contextExpressionsFieldSet.TryGetValue("Exclude", out excludeField))
                {
                    conditions.Exclude = excludeField.Values.ToArray();
                }

                entityModel.SetExtensionData(Constants.ContextExpressionsKey, conditions);
            }
        }
        /// <summary>
        /// Determines whether a given Entity Model should be included based on the conditions specified on the Entity Model and the context.
        /// </summary>
        /// <param name="entity">The Entity Model to be evaluated.</param>
        /// <param name="localization">The context Localization</param>
        /// <returns><c>true</c> if the Entity should be included.</returns>
        public bool IncludeEntity(EntityModel entity, Localization localization)
        {
            using (new Tracer(entity))
            {
                object ceExtensionData;
                if (entity.ExtensionData == null || !entity.ExtensionData.TryGetValue(Constants.ContextExpressionsKey, out ceExtensionData))
                {
                    // No Context Expressions defined for Entity: just include it.
                    return true;
                }
                ContextExpressionConditions ceConditions = (ContextExpressionConditions) ceExtensionData;

                IDictionary<string, object> contextClaims = GetCachedContextClaims(localization);

                if (!EvaluateContextExpressionClaims(ceConditions.Include, true, contextClaims))
                {
                    Log.Debug("Include Context Expression conditions are not satisfied; suppressing Entity [{0}].", entity);
                    return false;
                }
                if (!EvaluateContextExpressionClaims(ceConditions.Exclude, false, contextClaims))
                {
                    Log.Debug("Exclude Context Expression conditions are not satisfied; suppressing Entity [{0}].", entity);
                    return false;
                }

                Log.Debug("All resolved Context Expression conditions are satisfied; keeping Entity [{0}].", entity);
                return true;
            }
        }
        public virtual ActionResult Navigation(EntityModel entity, string navType, int containerSize = 0)
        {
            SetupViewData(entity, containerSize);

            INavigationProvider navigationProvider = SiteConfiguration.NavigationProvider;
            string requestUrlPath = Request.Url.LocalPath;
            Localization localization = WebRequestContext.Localization;
            NavigationLinks model;
            switch (navType)
            {
                case "Top":
                    model = navigationProvider.GetTopNavigationLinks(requestUrlPath, localization);
                    break;
                case "Left":
                    model = navigationProvider.GetContextNavigationLinks(requestUrlPath, localization);
                    break;
                case "Breadcrumb":
                    model = navigationProvider.GetBreadcrumbNavigationLinks(requestUrlPath, localization);
                    break;
                default:
                    throw new DxaException("Unexpected navType: " + navType);
            }

            EntityModel sourceModel = (EnrichModel(entity) as EntityModel) ?? entity;
            model.XpmMetadata = sourceModel.XpmMetadata;
            model.XpmPropertyMetadata = sourceModel.XpmPropertyMetadata;

            return View(sourceModel.MvcData.ViewName, model);
        }
        public virtual void BuildEntityModel(ref EntityModel entityModel, IComponentPresentation cp, Localization localization)
        {
            using (new Tracer(entityModel, cp, localization))
            {
                MvcData mvcData = GetMvcData(cp);
                Type modelType = ModelTypeRegistry.GetViewModelType(mvcData);

                // NOTE: not using ModelBuilderPipeline here, but directly calling our own implementation.
                BuildEntityModel(ref entityModel, cp.Component, modelType, localization);

                entityModel.XpmMetadata.Add("ComponentTemplateID", cp.ComponentTemplate.Id);
                entityModel.XpmMetadata.Add("ComponentTemplateModified", cp.ComponentTemplate.RevisionDate.ToString("yyyy-MM-ddTHH:mm:ss"));
                entityModel.XpmMetadata.Add("IsRepositoryPublished", cp.IsDynamic ? "true" : "false");
                entityModel.MvcData = mvcData;

                // add html classes to model from metadata
                // TODO: move to CreateViewModel so it can be merged with the same code for a Page/PageTemplate
                IComponentTemplate template = cp.ComponentTemplate;
                if (template.MetadataFields != null && template.MetadataFields.ContainsKey("htmlClasses"))
                {
                    // strip illegal characters to ensure valid html in the view (allow spaces for multiple classes)
                    entityModel.HtmlClasses = template.MetadataFields["htmlClasses"].Value.StripIllegalCharacters(@"[^\w\-\ ]");
                }

                if (cp.IsDynamic)
                {
                    // update Entity Identifier to that of a DCP
                    entityModel.Id = GetDxaIdentifierFromTcmUri(cp.Component.Id, cp.ComponentTemplate.Id);
                }
            }
        }
 protected virtual List<SyndicationItem> GetFeedItemsFromEntity(EntityModel entity)
 {
     List<SyndicationItem> items = new List<SyndicationItem>();
     IEnumerable<Teaser> entityItems = GetEntityItems(entity);
     foreach(Teaser item in entityItems)
     {
         items.Add(GetSyndicationItemFromTeaser(item));
     }
     return items;
 }
 private IEnumerable<Teaser> GetEntityItems(EntityModel entity)
 {
     List<Teaser> res = new List<Teaser>();
     //1. Check if entity is a teaser, if add it
     if (entity is Teaser)
     {
         res.Add((Teaser)entity);
     }
     else
     {
         //2. Second check if entity type is (semantically) a list, and if so, get its list items
         List<Teaser> items = GetTeaserListFromSemantics(entity);
         if (items != null)
         {
             res = items;
         }
         else
         {
             //3. Last resort, try to find some suitable properties using reflection
             Teaser teaser = new Teaser();
             foreach (PropertyInfo pi in entity.GetType().GetProperties())
             {
                 switch (pi.Name)
                 {
                     case "Headline":
                     case "Name":
                         teaser.Headline = pi.GetValue(entity) as String;
                         break;
                     case "Date":
                         DateTime? date = pi.GetValue(entity) as DateTime?;
                         if (date != null)
                             teaser.Date = date;
                         break;
                     case "Description":
                         teaser.Text = pi.GetValue(entity) as String;
                         break;
                     case "Link":
                         teaser.Link = pi.GetValue(entity) as Link;
                         break;
                     case "Url":
                         string url = pi.GetValue(entity) as String;
                         if (url != null)
                             teaser.Link = new Link { Url = url };
                         break;
                 }
             }
             if (teaser.Headline != null || teaser.Text != null || teaser.Link != null)
             {
                 res.Add(teaser);
             }
         }
     }
     return res;
 }
        public virtual ActionResult Entity(EntityModel entity, int containerSize = 0)
        {
            SetupViewData(entity, containerSize);

            ViewModel model = EnrichModel(entity);
            if (model is RedirectModel)
            {
                // Force a redirect (ASP.NET MVC doesn't allow child actions to redirect using RedirectResult)
                Response.StatusCode = (int) HttpStatusCode.Redirect;
                Response.RedirectLocation = ((RedirectModel) model).RedirectUrl;
                Response.End();
                return null;
            }

            return View(model.MvcData.ViewName, model);
        }
        public virtual void BuildEntityModel(ref EntityModel entityModel, IComponent component, Type baseModelType, Localization localization)
        {
            using (new Tracer(entityModel, component, baseModelType, localization))
            {
                string[] schemaTcmUriParts = component.Schema.Id.Split('-');
                SemanticSchema semanticSchema = SemanticMapping.GetSchema(schemaTcmUriParts[1], localization);

                // The semantic mapping may resolve to a more specific model type than specified by the View Model itself (e.g. Image instead of just MediaItem for Teaser.Media)
                Type modelType = semanticSchema.GetModelTypeFromSemanticMapping(baseModelType);

                MappingData mappingData = new MappingData
                {
                    SemanticSchema = semanticSchema,
                    EntityNames = semanticSchema.GetEntityNames(),
                    TargetEntitiesByPrefix = GetEntityDataFromType(modelType),
                    Content = component.Fields,
                    Meta = component.MetadataFields,
                    TargetType = modelType,
                    SourceEntity = component,
                    Localization = localization
                };

                entityModel = (EntityModel)CreateViewModel(mappingData);
                entityModel.Id = GetDxaIdentifierFromTcmUri(component.Id);
                entityModel.XpmMetadata = GetXpmMetadata(component);

                if (entityModel is MediaItem && component.Multimedia != null && component.Multimedia.Url != null)
                {
                    MediaItem mediaItem = (MediaItem)entityModel;
                    mediaItem.Url = component.Multimedia.Url;
                    mediaItem.FileName = component.Multimedia.FileName;
                    mediaItem.FileSize = component.Multimedia.Size;
                    mediaItem.MimeType = component.Multimedia.MimeType;
                }

                if (entityModel is Link)
                {
                    Link link = (Link)entityModel;
                    if (String.IsNullOrEmpty(link.Url))
                    {
                        link.Url = SiteConfiguration.LinkResolver.ResolveLink(component.Id);
                    }
                }
            }
        }
Esempio n. 9
0
 public void BuildEntityModel(ref EntityModel entityModel, IComponentPresentation cp, Localization localization)
 {
     // No post-processing of Entity Models needed
 }
 /// <summary>
 /// Generates semantic markup (HTML/RDFa attributes) for a given property of a given Entity Model.
 /// </summary>
 /// <param name="htmlHelper">The HtmlHelper instance on which the extension method operates.</param>
 /// <param name="entity">The Entity Model.</param>
 /// <param name="propertyName">The name of the property.</param>
 /// <param name="index">The index of the property value (for multi-value properties).</param>
 /// <returns>The semantic markup (HTML/RDFa attributes).</returns>
 public static MvcHtmlString DxaPropertyMarkup(this HtmlHelper htmlHelper, EntityModel entity, string propertyName, int index = 0)
 {
     return Markup.RenderPropertyAttributes(entity, propertyName, index);
 }
 /// <summary>
 /// Generates semantic markup (HTML/RDFa attributes) for a given Entity Model.
 /// </summary>
 /// <param name="htmlHelper">The HtmlHelper instance on which the extension method operates.</param>
 /// <param name="entity">The Entity Model to generate semantic markup for.</param>
 /// <returns>The HTML/RDFa attributes for the Entity. These should be included in an HTML start tag.</returns>
 public static MvcHtmlString DxaEntityMarkup(this HtmlHelper htmlHelper, EntityModel entity)
 {
     return Markup.RenderEntityAttributes(entity);
 }
        /// <summary>
        /// Renders a given Entity Model.
        /// </summary>
        /// <param name="htmlHelper">The HtmlHelper instance on which the extension method operates.</param>
        /// <param name="entity">The Entity to render.</param>
        /// <param name="containerSize">The size (in grid column units) of the containing element.</param>
        /// <returns>The rendered HTML or an empty string if <paramref name="entity"/> is <c>null</c>.</returns>
        public static MvcHtmlString DxaEntity(this HtmlHelper htmlHelper, EntityModel entity, int containerSize = 0)
        {
            if (entity == null)
            {
                return MvcHtmlString.Empty;
            }

            if (containerSize == 0)
            {
                containerSize = SiteConfiguration.MediaHelper.GridSize;
            }

            MvcData mvcData = entity.MvcData;
            using (new Tracer(htmlHelper, entity, containerSize, mvcData))
            {
                string actionName = mvcData.ActionName ?? SiteConfiguration.GetEntityAction();
                string controllerName = mvcData.ControllerName ?? SiteConfiguration.GetEntityController();
                string controllerAreaName = mvcData.ControllerAreaName ?? SiteConfiguration.GetDefaultModuleName();

                RouteValueDictionary parameters = new RouteValueDictionary();
                int parentContainerSize = htmlHelper.ViewBag.ContainerSize;
                if (parentContainerSize == 0)
                {
                    parentContainerSize = SiteConfiguration.MediaHelper.GridSize;
                }
                parameters["containerSize"] = (containerSize * parentContainerSize) / SiteConfiguration.MediaHelper.GridSize;
                parameters["entity"] = entity;
                parameters["area"] = controllerAreaName;
                if (mvcData.RouteValues != null)
                {
                    foreach (string key in mvcData.RouteValues.Keys)
                    {
                        parameters[key] = mvcData.RouteValues[key];
                    }
                }

                MvcHtmlString result = htmlHelper.Action(actionName, controllerName, parameters);
                // If the Entity is being rendered inside a Region (typical), we don't have to transform the XPM markup attributes here; it will be done in DxaRegion.
                if (!(htmlHelper.ViewData.Model is RegionModel) && WebRequestContext.IsPreview)
                {
                    result = new MvcHtmlString(Markup.TransformXpmMarkupAttributes(result.ToString()));
                }
                return result;
            }
        }
 public bool IncludeEntity(EntityModel entity, Localization localization)
 {
     _evaluatedEntities.Add(entity);
     return !ExcludeEntityIds.Contains(entity.Id);
 }
 public virtual ActionResult Entity(EntityModel entity, int containerSize = 0)
 {
     SetupViewData(entity, containerSize);
     EntityModel model = (EnrichModel(entity) as EntityModel) ?? entity;
     return View(model.MvcData.ViewName, model);
 }
        /// <summary>
        /// Renders a given Entity Model.
        /// </summary>
        /// <param name="htmlHelper">The HtmlHelper instance on which the extension method operates.</param>
        /// <param name="entity">The Entity to render.</param>
        /// <param name="viewName">The (qualified) name of the View used to render the entity. This overrides the View set in <see cref="EntityModel.MvcData"/>.</param>
        /// <param name="containerSize">The size (in grid column units) of the containing element.</param>
        /// <returns>The rendered HTML or an empty string if <paramref name="entity"/> is <c>null</c>.</returns>
        public static MvcHtmlString DxaEntity(this HtmlHelper htmlHelper, EntityModel entity, string viewName, int containerSize = 0)
        {
            MvcData mvcDataOverride = new MvcData(viewName);
            entity.MvcData.AreaName = mvcDataOverride.AreaName;
            entity.MvcData.ViewName = mvcDataOverride.ViewName;

            return htmlHelper.DxaEntity(entity, containerSize);
        }
 public ActionResult List(EntityModel entity, int containerSize = 0)
 {
     // The List action is effectively just an alias for the general Entity action (we keep it for backward compatibility).
     return Entity(entity, containerSize);
 }
Esempio n. 17
0
 public void BuildEntityModel(ref EntityModel entityModel, IComponent component, Type baseModelType, Localization localization)
 {
     // No post-processing of Entity Models needed
 }
        /// <summary>
        /// Renders a given Entity Model.
        /// </summary>
        /// <param name="htmlHelper">The HtmlHelper instance on which the extension method operates.</param>
        /// <param name="entity">The Entity to render.</param>
        /// <param name="viewName">The (qualified) name of the View used to render the entity. This overrides the View set in <see cref="EntityModel.MvcData"/>.</param>
        /// <param name="containerSize">The size (in grid column units) of the containing element.</param>
        /// <returns>The rendered HTML or an empty string if <paramref name="entity"/> is <c>null</c>.</returns>
        public static MvcHtmlString DxaEntity(this HtmlHelper htmlHelper, EntityModel entity, string viewName, int containerSize = 0)
        {
            MvcData mvcDataOverride = new MvcData(viewName);
            MvcData orginalMvcData = entity.MvcData;
            MvcData tempMvcData = new MvcData(orginalMvcData)
            {
                AreaName = mvcDataOverride.AreaName,
                ViewName = mvcDataOverride.ViewName
            };

            try
            {
                entity.MvcData = tempMvcData;
                return htmlHelper.DxaEntity(entity, containerSize);
            }
            finally
            {
                entity.MvcData = orginalMvcData;
            }
        }
        /// <summary>
        /// Maps Form data (for an HTTP POST request) to properies of a given Entity Model and performs basic validation.
        /// </summary>
        /// <param name="model">The Entity Model to map the form data to.</param>
        /// <returns><c>true</c> if there is any form data to be mapped.</returns>
        protected bool MapRequestFormData(EntityModel model)
        {
            if (Request.HttpMethod != "POST")
            {
                return false;
            }

            // CSRF protection: If the anti CSRF cookie is present, a matching token must be in the form data too.
            const string antiCsrfToken = "__RequestVerificationToken";
            if (Request.Cookies[antiCsrfToken] != null)
            {
                AntiForgery.Validate();
            }

            Type modelType = model.GetType();
            foreach (string formField in Request.Form)
            {
                if (formField == antiCsrfToken)
                {
                    // This is not a form field, but the anti CSRF token (already validated above).
                    continue;
                }

                PropertyInfo modelProperty = modelType.GetProperty(formField);
                if (modelProperty == null)
                {
                    Log.Debug("Model [{0}] has no property for form field '{1}'", model, formField);
                    continue;
                }

                string formFieldValue = Request.Form[formField];

                ValidationAttribute validationAttr = modelProperty.GetCustomAttribute<ValidationAttribute>();
                if (validationAttr != null)
                {
                    try
                    {
                        validationAttr.Validate(formFieldValue, formField);
                    }
                    catch (ValidationException ex)
                    {
                        string validationMessage = ResolveValidationMessage(ex.Message, model);
                        Log.Debug("Validation of property '{0}' failed: {1}", formField, validationMessage);
                        ModelState.AddModelError(formField, validationMessage);
                        continue;
                    }
                }

                try
                {
                    if (modelProperty.PropertyType == typeof (bool))
                    {
                        // The @Html.CheckBoxFor method includes a hidden field with the original checkbox state, resulting in two boolean values (comma separated)
                        formFieldValue = formFieldValue.Split(',')[0];
                    }
                    modelProperty.SetValue(model, Convert.ChangeType(formFieldValue, modelProperty.PropertyType));
                }
                catch (Exception ex)
                {
                    Log.Debug("Failed to set Model [{0}] property '{1}' to value obtained from form data: '{2}'. {3}", model, formField, formFieldValue, ex.Message);
                    ModelState.AddModelError(formField, ex.Message);
                }
            }

            return true;
        }
 public void BuildEntityModel(ref EntityModel entityModel, IComponent component, Type baseModelType, Localization localization)
 {
     // Nothing to do here
 }
 private List<Teaser> GetTeaserListFromSemantics(EntityModel entity)
 {
     Type type = entity.GetType();
     bool isList = false;
     foreach (object attr in type.GetCustomAttributes(true))
     {
         if (attr is SemanticEntityAttribute)
         {
             SemanticEntityAttribute semantics = (SemanticEntityAttribute)attr;
             isList = semantics.Vocab == ViewModel.SchemaOrgVocabulary && semantics.EntityName == "ItemList";
             if (isList)
             {
                 break;
             }
         }
     }
     if (isList)
     {
         foreach(PropertyInfo pi in type.GetProperties())
         {
             if (pi.PropertyType == typeof(List<Teaser>))
             {
                  return pi.GetValue(entity) as List<Teaser>;
             }
         }
     }
     return null;
 }