4

I have created a Schema, say ABC, which has a multivalued Component Link field. There are multiple allowed Schemas in the field, say A & B. How can we map this field when we create the Model for it in .NET DXA Application?

For one allowed Schema, I can do it straight forward.

public List<A> field { get; set; }

How can we handle, if multiple Schemas are allowed?

4 Answers 4

6

You need to create multiple properties corresponding the allowed Schema. The Semantic Property for all allowed schemas should be same. It should look something like this.

[SemanticProperty("Schema_Field")]
public List<SchemaModelA> A{ get; set; }
[SemanticProperty("Schema_Field")]
public List<SchemaModelB> B{ get; set; }
[SemanticProperty("Schema_Field")]
public List<SchemaModelC> C{ get; set; }
2
  • Hi Manish, I tried this way, but it doesn't work. It gives Null for both the fields, even if the components are linked in the Main Component. Commented Sep 2, 2016 at 10:10
  • Hi Manish, I was missing the SemanticEntity Entry for the LInked Schemas. Once I did that, it worked. Thanks for the help Commented Sep 2, 2016 at 12:43
5

You can create separate View Model types for each Schema (ensure you have a proper semantic mappings to the Schemas on type level).

If you want a property to be able to refer to multiple View Model types, just use a common base type. All your View Model types will have EntityModel as base type, so you could use that.

However, it is more elegant (more strongly typed) to define your own (abstract) base class (which itself is a subclass of EntityModel) from which your concrete types inherit. This also allows you to put common properties/methods in the base class,

The DXA model mapping will automatically instantiate the appropriate concrete subclass based on semantic mapping.

5

As Rick mentioned, you can implement support for multiple schemas in component link by creating your own abstract base class, from which your different model types will inherit. There are couple of caveats, so I am posting detailed step by step instructions here:

  1. Create Base class

    public abstract class BaseSchemaModelABC : EntityModel
    {
        public string CommonProperty { get; set; }
    }
    

    Base class must inherit from EntityModel

  2. Include into your main schema model new property with type List of BaseSchemaModelABC

    public List<BaseSchemaModelABC> ComponentLinks { get; set; }
    

    If your new property is always null, check the name of this field in your schema. You need to remove any trailing s's from the field name. For example, it will not work if your schema field xml name is componentLinks. It has to be componentLink

  3. Create models for linked schemas that will inherit from Base class

    [SemanticEntity(EntityName ="SchemaA",Prefix = "s", Vocab = CoreVocabulary)]
    public class SchemaModelA : BaseSchemaModelABC
    {
        public string FieldA { get; set; }
    }
    
    [SemanticEntity(EntityName = "SchemaB", Prefix = "s", Vocab = CoreVocabulary)]
    public class SchemaModelB : BaseSchemaModelABC
    {
        public string FieldB { get; set; }
    }
    

    Set SemanticEntity Vocab to CoreVocabulary, otherwise it did not work for me

  4. Register Models in your AreaRegistration.cs

    RegisterViewModel("SchemaAView", typeof(SchemaModelA), controllerName: "NameOfCustomController");
    RegisterViewModel("SchemaBView", typeof(SchemaModelB), controllerName: "NameOfCustomController");
    

    This is the most important part. Even if you don't have view for your view models, you have to register them

9
  • Ad 2. Indeed, there is some "de-pluralization" happening in the implicit semantic mapping (the idea is that it's more natural to have singular names for CM fields even if they are multi-values: have a look at the source XML in CM). If you don't want this, you can put an explicit SemanticProperty annotation on the property. Commented Mar 29, 2017 at 6:22
  • Ad 3. Indeed, implicity semantic mapping (on CM-side) is done using the Core Vocabulary. Since DXA 1.7, it is no longer required to explicitly set the Vocab; Core Vocabulary is now the default. Commented Mar 29, 2017 at 6:25
  • Ad 4. Indeed, even "embedded" View Models (for which you don't have a separate View) must be registered, but note that there is an overload of RegisterViewModel which only takes a Type parameter for that purpose. Commented Mar 29, 2017 at 6:26
  • @RickPannekoek thanks for comments. Regarding explicit SemanticProperty, I have tried it in DXA 1.6 and it still did not work. Probably worth testing, or maybe it was fixed for DXA 1.7. Commented Mar 29, 2017 at 17:09
  • Note that if you use a Prefix in your SemanticEntity annotation (which I would not recommend), you must also use that in your SemanticProperty annotation. For example: [SemanticProperty("s:componentLink")]. Did you try that? Commented Mar 29, 2017 at 17:42
1

@Sharad, way of mapping linked components on a model may change based on your requirement. Below are some way to bind the linked components in the model. You can check which way suits for you.

You can create a model with all the required fields which you required in the view. You can see Teaser.cs model in core area as an example. This Model is created for multiple schemas.

You can get all the fields of a linked component as a dictionary in a field if you use Link type to map linked components. In its LinkProperties you will get all fields.

The way which Manish has suggested should also work. In this case you need to identify which field has your mapped data inside controller.

Please share if you are facing any issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.