0

I'm using dotnet ef scaffold to generate model classes from an existing database "Microsoft.EntityFrameworkCore.Tools"

Everything works and models get generated with data annotations as expected and asp.net controller returns Json no issues.

using the [JsonIgnore] decorator helps to remove the fields that I do NOT want the api to return. (like Id's etc)

I would like to use a partial class that is not gonna be overwritten when you scaffold a new DbContext. (bonus if it could be in another assembly) Newtonsoft lets me handle nulls,dates and reference loops - I would like all that goodness to be kept separate from all EF's annotations.

I know there are other techniques, but this seems like a good use case for Partial classes ... like with the jQuery unobtrusive validation that comes with ASP.Net MVC out the box ... but I've hit a roadblock on this one ... so is this even possible or am I missing something obvious :|

Model generated by Entity Framework

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Newtonsoft.Json;

namespace SomeNamespace
{
    public partial class Media
    {
        public int Id { get; set; }

        public int SiteId { get; set; }

        public Guid Ref { get; set; }

        [Required]
        [StringLength(2000)]
        public string Url { get; set; }

        public string Caption { get; set; }

        [ForeignKey("SiteId")]
        [InverseProperty("Media")]
        public Site Site { get; set; }
    }
}

Partial Class

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;    
using Microsoft.AspNetCore.Mvc; // "ModelMetadataType"
using Newtonsoft.Json;

namespace SomeNamespace
{
    [ModelMetadataType(typeof(MediaMetaData))]
    public partial class Media
    {
    }
    public partial class MediaMetaData
    {
        [JsonIgnore]
        public int Id { get; set; }

        [JsonIgnore]
        public int SiteId { get; set; }

        [JsonIgnore]
        public Site Site { get; set; }
    }
}

:( => UPDATE : 23 Jan 2018

I get the comment from this answer How to use ASP.Net core ModelMetadata attribute

"because you are trying to use the metadata type of a derived class to rename the properties in a base type"

I can appreciate Liskov, but then is a Partial Class is actually a Derived Class ??

What I don't get is that the [JsonIgnore] works when applied in the EF model like so ...

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;    
using Microsoft.AspNetCore.Mvc; // "ModelMetadataType"
using Newtonsoft.Json;

namespace SomeNamespace
{
    public partial class Media
    {
        [JsonIgnore]
        public int Id { get; set; }

        [JsonIgnore]
        public int SiteId { get; set; }

        public Guid Ref { get; set; }

        [Required]
        [StringLength(2000)]
        public string Url { get; set; }

        public string Caption { get; set; }

        [JsonIgnore]
        [ForeignKey("SiteId")]
        [InverseProperty("Media")]
        public Site Site { get; set; }
    }
}

and produces the following ...

{
  "ref": "0c0e1475-63a1-41ce-9c6f-b4be6afd516a",
  "url": "https://drive.com/images/fb65a200",
  "caption": "bla bla"
}

it's what I want... but that gets overwritten when using code generation (the problem that partial classes were supposed to solve)

but by using partial classes as in my original question above I get this...

{
  "id": 7,
  "siteId": 2000,
  "ref": "0c0e1475-63a1-41ce-9c6f-b4be6afd516a",
  "url": "https://drive.com/images/fb65a200",
  "caption": "bla bla",
  "site": {...}
}
George Albertyn
  • 267
  • 4
  • 11
  • You know you can do all the EF annotations in the OnModelCreating inside the DbContext? If you move all your EF Attributes to there you can focus on Json Attributes inside your class files. – Meikel Jan 22 '18 at 22:51
  • have you tried a MetadataTypeAttribute https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.metadatatypeattribute?view=netframework-4.7.1&viewFallbackFrom=netcore-2.0 ? – David Browne - Microsoft Jan 22 '18 at 23:01
  • So the DbContext along with the models is what gets overwritten every time you run scaffold ... I should be using migrations ... love... hate... but yea new files every time ... thanks for the suggestion tho – George Albertyn Jan 22 '18 at 23:08
  • @DavidBrowne-Microsoft ... you almost made my day but that type or namespace could not be found ... https://stackoverflow.com/questions/34576921/asp-net-core-metadatatype-attribute-not-working – George Albertyn Jan 22 '18 at 23:15
  • `ModelMetadataType` is not currently supported by Json.NET. On this topic [Issue #1349: Add support for ModelMetadataType for dotnetcore like supported MetadataTypeAttribute in previous versions](https://github.com/JamesNK/Newtonsoft.Json/issues/1349) was closed by James Newton-King with the comment, *I don't want to have dependencies on features in individual libraries. If MetadataTypeAttribute is added back to .NET Core then I will add support for it.* You could add a comment or vote to the github issue if it's important to you. – dbc Jan 22 '18 at 23:28
  • Ah found a duplicate: [How to use ASP.Net core ModelMetadata attribute](https://stackoverflow.com/q/47164280/3744182). – dbc Jan 22 '18 at 23:31
  • @dbc is a partial class the same as a base class? – George Albertyn Jan 24 '18 at 04:21
  • @Terminator - A [partial class](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/partial-classes-and-methods) is just a class whose definition happens to be split up amongst multiple files, for editing convenience. Once compiled there's no difference between a partial class and a single-file class, but having the class definition in multiple files can make some things easier, like merging in changes from a code generation tool by having the auto-generated code in a completely separate file. – dbc Jan 24 '18 at 04:39
  • See also [When is it appropriate to use C# partial classes?](https://stackoverflow.com/q/3601901) and [Are C#'s partial classes bad design?](Are C#'s partial classes bad design?) – dbc Jan 24 '18 at 04:42
  • @Terminator - OK, I just saw your edit. Basically your question is *simpler* than the linked question. In that question the OP was trying to apply `ModelMetadataType` to a class *to control class serialization **and base class serialization***. In your case you are trying to apply to a class *to control class serialization only*. But the answer is basically the same, namely that support for `ModelMetadataType` is not implemented in Json.NET. The answer there gives some possible workarounds that would also work for your simpler problem. – dbc Jan 24 '18 at 05:47
  • @dbc Yea - no rocket science going on here ... so after reading this for the 3rd time https://stackoverflow.com/questions/45045546 I'm beginning to understand what you mean by `ModelMetadataType` is not implemented in Json.NET... because ... if it's "not implemented" how the hell does it work when applied to the EF model only (sigh) ... at any rate - thank you for your advice and if you're ever in Cape Town swing by for a coffee! – George Albertyn Jan 24 '18 at 07:24

0 Answers0