Blazor webassembly with Entity Framework fails with "ContentType is not supported; the supported types are 'application/json'"

Viewed 763

This is a simple CRUD application I am using to learn how this works. I have used Entity Framework before, but know very little about how it works. This app has a database with one table, Employee, with 6 common type columns. I downloaded a working copy of the same app written before System.Text.Json, so the database connection is working.

The call in GetEmployee.razor is:

@code {
    private Employee[] empList;
    protected override async Task OnInitializedAsync()
    {
        try
        {
            empList = await Http.GetFromJsonAsync<Employee[]>("/api/Employee/Index");
        }
        catch (Exception ex)
        {
            string foo = ex.ToString();
        }
    }
}

namespace Clean.Server.Api
{
    public partial class ManagementContext : DbContext
    {
        public ManagementContext()
        {
        }

        public ManagementContext(DbContextOptions<ManagementContext> options)
            : base(options)
        {
        }

        public virtual DbSet<Employee> Employee { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
                optionsBuilder.UseSqlServer("Server=MtLyell\\SQLEXPRESS;Database=Management;Integrated Security=True;");
            }
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Employee>(entity =>
            {
                entity.Property(e => e.Designation)
                    .HasMaxLength(100)
                    .IsUnicode(false);

                entity.Property(e => e.Email)
                    .HasMaxLength(20)
                    .IsUnicode(false);

                entity.Property(e => e.Location)
                    .IsRequired()
                    .HasMaxLength(50)
                    .IsUnicode(false);

                entity.Property(e => e.Name)
                    .IsRequired()
                    .HasMaxLength(100)
                    .IsUnicode(false);
            });

            OnModelCreatingPartial(modelBuilder);
        }

        partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
    }
}

amespace Clean.Server.Api
{
    public partial class Employee
    {
        public long EmployeeId { get; set; }
        public string Name { get; set; }
        public string Designation { get; set; }
        public string Email { get; set; }
        public string Location { get; set; }
        public long PhoneNumber { get; set; }
    }
}

namespace Clean.Server.Api
{
    public interface IEmployeAccessLayer
    {
        IEnumerable<Employee> GetAllEmployees();
        void AddEmployee(Employee employee);
        void UpdateEmployee(Employee employee);
        Employee GetEmployeeData(long id);
        void DeleteEmployee(long id);
    }

    public class EmployeAccessLayer : IEmployeAccessLayer
    {
        private ManagementContext _context;
        public EmployeAccessLayer(ManagementContext context)
        {
            _context = context;
        }

        //To Get all employees details   
        public IEnumerable<Employee> GetAllEmployees()
        {
            try
            {
                return _context.Employee.ToList();
            }
            catch(Exception ex)
            {
                throw;
            }
        }

        //To Add new employee record     
        public void AddEmployee(Employee employee)
        {
            try
            {
                _context.Employee.Add(employee);
                _context.SaveChanges();
            }
            catch
            {
                throw;
            }
        }

        //To Update the records of a particluar employee    
        public void UpdateEmployee(Employee employee)
        {
            try
            {
                _context.Entry(employee).State = EntityState.Modified;
                _context.SaveChanges();
            }
            catch
            {
                throw;
            }
        }

        //Get the details of a particular employee    
        public Employee GetEmployeeData(long id)
        {
            try
            {
                Employee employee = _context.Employee.Find(id);
                return employee;
            }
            catch
            {
                throw;
            }
        }

        //To Delete the record of a particular employee    
        public void DeleteEmployee(long id)
        {
            try
            {
                Employee emp = _context.Employee.Find(id);
                _context.Employee.Remove(emp);
                _context.SaveChanges();
            }
            catch
            {
                throw;
            }
        }
    }
}

namespace Clean.Server.Controllers
{
    public class EmployeeController : ControllerBase
    {
        IEmployeAccessLayer _employee;

        public EmployeeController(IEmployeAccessLayer employee)
        {
            _employee = employee;
        }

        [HttpGet]
        [Route("api/Employee/Index")]
        public IEnumerable<Employee> Index()
        {
            return _employee.GetAllEmployees();
        }

        [HttpPost]
        [Route("api/Employee/Create")]
        public void Create([FromBody] Employee employee)
        {
            if (ModelState.IsValid)
                this._employee.AddEmployee(employee);
        }

        [HttpGet]
        [Route("api/Employee/Details/{id}")]
        public Employee Details(int id)
        {
            return _employee.GetEmployeeData(id);
        }

        [HttpPut]
        [Route("api/Employee/Edit")]
        public void Edit([FromBody]Employee employee)
        {
            if (ModelState.IsValid)
                this._employee.UpdateEmployee(employee);
        }

        [HttpDelete]
        [Route("api/Employee/Delete/{id}")]
        public void Delete(int id)
        {
            _employee.DeleteEmployee(id);
        }
    }
}

The error message more completely is:

The provided ContentType is not supported; the supported types are 'application/json' and the structured syntax suffix 'application/+json'

To convert the entity objects to Json, there is JsonSerializer.Serialize() which I have tried applying to the GetAllEmployees method in EmployeeAccessLayer.cs. The result was:

Cannot implicitly convert type string to System.Collections.Generic.IEnumerable

I may eventually work out how to do this.

return JsonSerializer.Serialize(_context.Employee.ToList());

Is serialization in EmployeeAccessLayer.cs the right idea and place to do this conversion?

And if so, how do I convert it to the right type?

Or is there a setting in EF that would do it for me?

1 Answers

In Startup.cs I needed to register ManagementContext and IemployeAccessLayer which I did:

public static string Connection { get; set; }
            Connection = Configuration.GetConnectionString("EmployeeDatabase");
            services.AddDbContext<ManagementContext>(options => options.UseSqlServer(Connection));
            services.AddScoped<IEmployeAccessLayer, EmployeAccessLayer>();

and in ManagementContext.cs I changed OnConfiguring:

optionsBuilder.UseSqlServer(Clean.Server.Startup.Connection);

The json commands that seem to work (minimal testing) in the razor files are: GetFromJsonAsync, PutAsJsonAsync, DeleteAsync, PostAsJsonAsync

Related