Enum issue

M Jyothi 0 Reputation points
2023-10-13T07:07:10.7666667+00:00

When I passing integers to the enum it is accepting but I want to throw an error for integers. need to pass strings only in my API and also for empty values need to add default one to the database. How can I do that in API C#

C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,370 questions
{count} votes

2 answers

Sort by: Most helpful
  1. Gabriele Tronchin 0 Reputation points
    2023-10-13T15:12:00.4366667+00:00

    Hi @Anonymous ,

    By default enum are integer in c#.

    If you want to work with enum name istead of value you there are 2 way:

    • using a serializer attribute for a specific enum
    • set in you program.cs a specific converter for all enums type

    To do that the first step is identify which serializer are you using in your API, by default is "System.Text.Json" but an other popular options is "NewtonsoftJson".

    Here few piece of code that may help you to set these way of work globally in your API:

    NewtonsoftJson

                    .AddNewtonsoftJson(options =>
                    {
                        options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                        options.SerializerSettings.Converters.Add(new StringEnumConverter());
                    });
    

    System.Text.Json

                    .AddJsonOptions(opts =>
                    {
                        var enumConverter = new JsonStringEnumConverter();
                        opts.JsonSerializerOptions.Converters.Add(enumConverter);
    
                    })
    

    After that every time in your models you have a enum, it will work by enum name.

    Speaking about default value you should set it on your API model.

    Hope these help you,

    Best regards

    0 comments No comments

  2. Karen Payne MVP 35,201 Reputation points
    2023-10-14T18:13:11.01+00:00

    Lets say you were using EF Core, given

    Main table/model

    public class Wine
    {
        public int WineId { get; set; }
        public string Name { get; set; }
        public WineType WineType { get; set; }
        public override string ToString() => $"{WineType} {Name}";
    }
    

    Navigation

    [Table("WineType")]
    public class WineTypes
    {
        [Key]
        public int Id { get; set; }
        public string TypeName { get; set; }
        public string  Description { get; set; }
    }
    

    DbContext

    public class WineContext : DbContext
    {
        public DbSet<Wine> Wines { get; set; }
        public DbSet<WineTypes> WineTypes { get; set; }
    
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            => optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=EF.Wines;Trusted_Connection=True");
    
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder
                .Entity<Wine>()
                .Property(e => e.WineType)
                .HasConversion<int>();
    
            modelBuilder.Entity<WineTypes>().HasData(
                new WineTypes() {Id = 1, TypeName = "Red", Description = "Classic red"},
                new WineTypes() {Id = 2, TypeName = "White", Description = "Dinner white"},
                new WineTypes() {Id = 3, TypeName = "Rose", Description = "Imported rose"}
            );
    
            modelBuilder.Entity<Wine>().HasData(
                new Wine() { WineId = 1, Name = "Veuve Clicquot Rose", WineType = WineType.Red },
                new Wine() { WineId = 2, Name = "Whispering Angel Rose", WineType = WineType.Rose },
                new Wine() { WineId = 3, Name = "Pinot Grigi", WineType = WineType.White },
                new Wine() { WineId = 4, Name = "White Zinfandel", WineType = WineType.Rose }
            );
        }
    }
    

    It is not possible to set WineType property of Wine to an int but the value is stored as an int which is proper as if the string value changes that creates issues so to fix this we use a .tt file to recreate WineType.

    <#@ template debug="true" hostSpecific="true" #>
    <#@ output extension=".cs" #>
    <#@ Assembly Name="EnvDTE.dll" #>
    <#@ Assembly Name="System.Data" #>
    <#@ import namespace="EnvDTE" #>
    <#@ import namespace="System.Data" #>
    <#@ import namespace="System.Data.SqlClient" #>
    <#@ import namespace="System.IO" #>
    <#@ import namespace="System.Text.RegularExpressions" #>
    <#
        var tableName = Path.GetFileNameWithoutExtension(Host.TemplateFile);
        var path = Path.GetDirectoryName(Host.TemplateFile);
        var columnId = "Id";
        var columnName = "TypeName";
    	var columnDescription = "Description";
        var connectionString = "Server=(localdb)\\mssqllocaldb;Database=EF.Wines;Trusted_Connection=True";
    	IServiceProvider serviceProvider = (IServiceProvider)Host;
    	DTE dte = (DTE)serviceProvider.GetService(typeof(DTE));
    	Project project = dte.Solution.FindProjectItem(Host.TemplateFile).ContainingProject;
    #>
    using System.CodeDom.Compiler;
    using System.ComponentModel;
    
    namespace <#= project.Properties.Item("DefaultNamespace").Value #><#= Path.GetDirectoryName(Host.TemplateFile).Remove(0, Path.GetDirectoryName(project.FileName).Length).Replace("\\", ".") #>
    {
        /// <summary>
        /// <#= tableName #> auto generated enumeration
        /// </summary>
        [GeneratedCode("TextTemplatingFileGenerator", "10")]
        public enum <#= tableName #>
        {
    <#
        SqlConnection conn = new SqlConnection(connectionString);
        string command = $"select {columnId}, {columnName}, {columnDescription} from {tableName} order by {columnId}";
        SqlCommand comm = new SqlCommand(command, conn);
    
        conn.Open();
        SqlDataReader reader = comm.ExecuteReader();
        bool loop = reader.Read();
    
        while(loop)
        {
    #>        [Description("<#= reader[columnDescription] #>")] 
            <#= Pascalize(reader[columnName]) #> = <#= reader[columnId] #><# loop = reader.Read(); #><#= loop ? ",\r\n" : string.Empty #><#
        }
    #>
    }
    }
    <#+
        private string Pascalize(object value)
        {
    		Regex rx = new Regex(@"(?:[^a-zA-Z0-9]*)(?<first>[a-zA-Z0-9])(?<reminder>[a-zA-Z0-9]*)(?:[^a-zA-Z0-9]*)");
            return rx.Replace(value.ToString(), m => m.Groups["first"].ToString().ToUpper() + m.Groups["reminder"].ToString().ToLower());
        }
    #>
    
    0 comments No comments