I want to do get, post, put and delete in it using asp.net core Web API. But I should not use database to store the data instead I need to store the dynamic data in controller using method and also in json file list of user(userId,userName),3 level hierarchy(Country should have list of state,State should have list of city,And I could add Countries along with its states and cities) and use it to do the http action. Can any one please help me with some step or code?
I create a sample demo for you, and I suggest you don't use json file.
Why:
When you use json files, IO operations are required, and there will be a problem of exclusive use of files.
In addition, when adding, deleting, modifying and checking the content of the file, every time there is a json file that is read, then converted into an object, and then written into the file, the efficiency will be very low.
Because what you want is a demo, the test code I wrote does not have any verification. You can pay attention to the places that need attention.
AddSingleton must be used when registering a service, so as to ensure that all users access the same data source.
When the amount of data is very large and there are too many requests, there will be a situation where the data does not match. Because I have not added any locks or restrictions here.
Test Result
Test Code:
Create GlobalVariablesService, and register it
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace DB_Project.Models
{
public class GlobalVariablesService
{
public List<RecordModel> records = new List<RecordModel>();
public GlobalVariablesService(){
}
public List<RecordModel> AddRecord(RecordModel r) {
records.Add(r);
return records;
}
public List<RecordModel> RemoveRecord(int rid)
{
var itemToRemove = records.Single(r => r.Record_ID == rid);
records.Remove(itemToRemove);
return records;
}
public RecordModel GetRecord(int rid)
{
var itemToGet = records.Single(r => r.Record_ID == rid);
return itemToGet;
}
}
/// <summary>
/// Add Record History
/// Rid #Uid #Country_id #Country_Name #State_id #State_Name #City_id #City_Name
/// 1 001 C1 Country1 S1 State1 C_1 City1
/// 2 002 C2 Country2 S2 State2 C_2 City2
/// 3 003 C3 Country3 S3 State3 C_3 City3
/// </summary>
///
public class RecordModel {
public int Record_ID { get; set; }
public int Uid { get; set; }
public string Country_id { set; get; }
public string Country_Name { set; get; }
public string State_id { set; get; }
public string State_Name { set; get; }
public string City_id { set; get; }
public string City_Name { set; get; }
}
public class UserModel {
public int Uid { set; get; }
public string Name { set; get; }
}
public class CountryModel
{
public string Country_id { set; get; }
public string Country_Name { set; get; }
public List<StateModel> State { set; get; }
}
public class StateModel
{
public string State_id { set; get; }
public string State_Name { set; get; }
public List<CityModel> City { set; get; }
}
public class CityModel
{
public string City_id { set; get; }
public string City_Name { set; get; }
}
}
Register service in Startup.cs file;
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddSingleton<GlobalVariablesService>();
}
My Test Controller
using DB_Project.DbClass;
using DB_Project.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace DB_Project.Controllers
{
public class TestController : Controller
{
private readonly ILogger<TestController> _logger;
private readonly GlobalVariablesService _service;
public TestController(ILogger<TestController> logger, GlobalVariablesService service)
{
_logger = logger;
_service = service;
}
public IActionResult get(int rid)
{
try
{
var model = _service.GetRecord(rid);
return Ok(model);
}
catch (Exception e)
{
return Ok("error occured :" + e.ToString());
throw;
}
}
public string add(RecordModel r)
{//string uid,string countryid,string countryname,string stateid,string statename,string cityid,string cityname ) {
try
{
_service.AddRecord(r);
return "success";
}
catch (Exception)
{
return "failed";
throw;
}
}
public string delete(int rid){
try
{
_service.RemoveRecord(rid);
return "success";
}
catch (Exception)
{
return "failed";
throw;
}
}
}
}
Everything looks good but I don't understand why I still get an error like:
"System.InvalidCastException: The field of type DotnetCoreWebAPI.Enum+Blood must be a string, array or ICollection type."
I've left some meaningful snippets of code and the error I'm getting, below.
Model:
public class User
{
[Key]
public int Id { get; set; }
[Required]
[MaxLength(100)]
public string Name { get; set; }
[MaxLength(100)]
public string Surname { get; set; }
[MaxLength(2)]
public Enum.Blood Blood { get; set; }
[MaxLength(50)]
public string Cellphone { get; set; }
[MaxLength(500)]
public string Adress { get; set; }
}
Enum:
public class Enum
{
public enum Blood
{
ARhDpositive,
ARhDnegative,
BRhDpositive,
BRhDnegative,
ORhDpositive,
ORhDnegative,
ABRhDpositive,
ABRhDnegative
}
}
Controller:
[HttpPost]
public ActionResult<UserReadDto> CreateUser(User userCreateDto)
{
var userModel = _mapper.Map<User>(userCreateDto);
_repository.CreateUser(userModel);
return Ok(userModel);
}
Service Configurations:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<UserContext>(opt => opt.UseSqlServer
(Configuration.GetConnectionString("DatabaseConnection")));
services.AddControllers().AddJsonOptions(opt =>
opt.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));
services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
services.AddScoped<IUserRepo, SqlUserRepo>();
}
Note:
I use Postman when I test api
I found out why problem occurs, I've wrote User instead of UserCreateDto in this line:
public ActionResult<UserReadDto> CreateUser(**UserCreateDto ** userCreateDto)
In a .Net 5 Web Api application, I am reading some rows from a MySql table (using the Pomelo library).
I am using a raw sql query. So:
MySqlParameter propertyIdParam = new MySqlParameter()
{
ParameterName = "#propertyId",
MySqlDbType = MySqlDbType.Int32,
Direction = System.Data.ParameterDirection.Input,
Value = 7
};
List<PropertyRepairsDto> propertyRepairs = await _context.PropertyRepairs
.FromSqlRaw("some sql query", propertyIdParam)
.AsNoTracking()
.ToListAsync();
The strange thing is that this works well, until I provide a parameter ("propertyId") which doesn't exist - so that the query returns no rows. In that case, I get the following exception:
System.InvalidCastException: Specified cast is not valid.
at MySqlConnector.Core.Row.GetInt32(Int32 ordinal) in /_/src/MySqlConnector/Core/Row.cs:line 211
at MySqlConnector.MySqlDataReader.GetInt32(Int32 ordinal) in /_/src/MySqlConnector/MySqlDataReader.cs:line 238
at lambda_method848(Closure , QueryContext , DbDataReader , Int32[] )
at Microsoft.EntityFrameworkCore.Query.Internal.FromSqlQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at PropWorx.API.Controllers.PropertiesController.GetPropertyRepairsAsync(Int32 id) in C:\Users\fabsr\source\repos\PropWorx.API\PropWorx.API\Controllers\PropertiesController.cs:line 194
at lambda_method479(Closure , Object )
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Logged|12_1(ControllerActionInvoker invoker)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at PropWorx.API.Middlewares.TenantIdentifier.Invoke(HttpContext httpContext, SharedContext sharedContext) in C:\Users\fabsr\source\repos\PropWorx.API\PropWorx.API\Middlewares\TenantIdentifier.cs:line 52
at PropWorx.API.Middlewares.WebSocketsMiddleware.Invoke(HttpContext httpContext) in C:\Users\fabsr\source\repos\PropWorx.API\PropWorx.API\Middlewares\WebSocketsMiddleware.cs:line 28
at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
HEADERS
=======
Connection: keep-alive
Content-Type: application/json
Accept: */*
Accept-Encoding: gzip, deflate, br
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ik1ERXpSRUUwUWpFMk9VTkdOa0kyUlRJMFJEUXdNakExUTBFeE1EUkNRalpDUmtWR1JVTXhOQSJ9.eyJpc3MiOiJodHRwczovL2NvZGV4Y3JlYXRpb25zLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw1OTI2YjEwYTAxZTkxZDE0MGU5OWVlNjQiLCJhdWQiOlsiaHR0cHM6Ly9wcm9wd29yeC5jby56YS9hcGkiLCJodHRwczovL2NvZGV4Y3JlYXRpb25zLmV1LmF1dGgwLmNvbS91c2VyaW5mbyJdLCJpYXQiOjE2MTAwMDkyMjQsImV4cCI6MTYxMjYwMTIyNCwiYXpwIjoiUnppNzVkU1dpcVlFYlJsVjU1N0lFd1dQYUI5Qmwzd3giLCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIn0.WK2gtsbWtiz1WIkJrO56Ap8fqyyyLBs1wiKcs0KvTVTPKlzVyicf6J9S-9PMDGs1uT-gho7fVW6gLVv9XzLCulcR4x3KFrNmLSW9lvsj9fyKPMQ4Udp4A2UdfYoogRXduB62QwqRhkYGbNkI-tSGgMwF-zgClirKalpY6oKs9yMY6qr_XC4ZzTI27Pd4W9wverLtLT0-1WNlh4ynUF_xE5uvfKfh0KhBITs-KASUBMz7WcloSehNqvnkwOOdLCcWtkcbcms4LRklwEzpQvXiuCwAgjpjq980fjFjYSISjD5paqBM_rdpvG4Yz4OqI6FXtccuszbc_1WcXe7O_CSuTg
Host: localhost:5001
Referer: http://localhost:5000/api/properties/6823/repairs
User-Agent: PostmanRuntime/7.26.8
Content-Length: 2856
clientId: 273
Postman-Token: fe2fcc49-3f1b-451b-8e06-b808fa28964c
I don't understand how it's possible that it works fine when the query returns rows (so it's mapping the database data correctly to the model fields), but when the query returns no rows (which I would assume should simply result in a List of zero items) it throws an exception.
The exception suggests a problem converting a value from the database to int32. At first, I thought it might be a null that's trying to be mapped to a non-nullable integer in my model, but ALL integer fields in my model are nullable. But even so, since the query is not returning any rows, surely it shouldnt even be a problem as there is nothing to map?
I know it's difficult to assist me without seeing the database structures, models, queries, etc. It's just that the query and tables are quite big, and I thought perhaps someone has experienced this problem before, where things work until a query is called which returns no rows, in which case a System.InvalidCastException is thrown.
Here is the model I am mapping to, for what it's worth:
public class PropertyRepairsDto
{
public int? Id { get; set; }
public int? FileId { get; set; }
public string FileNum { get; set; }
public bool? IsRequired { get; set; }
public string Info { get; set; }
public bool? QuotesObtained { get; set; }
public decimal? QuoteAmount { get; set; }
public string ContractorAppointed { get; set; }
public bool? IsPaid { get; set; }
public decimal? AmountPaid { get; set; }
public DateTime? JobDate { get; set; }
public bool? PaymentRequired { get; set; }
public DateTime? PaymentDate { get; set; }
public string PaymentReference { get; set; }
public DateTime? ReportedAt { get; set; }
public int? ContractorId { get; set; }
public string Contractor { get; set; }
public bool? IsFixedByOwner { get; set; }
public DateTime? FollowUpDate { get; set; }
public string WorkOrderNumber { get; set; }
public bool? IsCompleted { get; set; }
public DateTime? CompletedDate { get; set; }
public bool? IsInvoiceReceived { get; set; }
public DateTime? InvoiceReceivedAt { get; set; }
public decimal? InvoiceAmount { get; set; }
public bool? IsInvoiceApproved { get; set; }
public DateTime? InvoiceApprovedAt { get; set; }
public string InvoiceApprovedBy { get; set; }
public bool? ChargeToTenant { get; set; }
public bool? IsReportedToOwner { get; set; }
public DateTime? ReportedToOwnerAt { get; set; }
public int? InvoiceDocId { get; set; }
public int? ReportedById { get; set; }
public string ReportedBy { get; set; }
public int? PriorityId { get; set; }
public string Priority { get; set; }
public int? QuotesRequired { get; set; }
public bool? InvoiceOwner { get; set; }
public bool? InvoiceTenant { get; set; }
public bool? IsReportSentToTenant { get; set; }
public DateTime? ReportSentToTenantAt { get; set; }
public bool? IsJobCardSentToServiceProvider { get; set; }
public int? JobCardSentToId { get; set; }
public string JobCardSentTo { get; set; }
public int? JobCardSentToServiceProviderById { get; set; }
public string JobCardSentToServiceProviderBy { get; set; }
public DateTime? JobCardSentToServiceProviderAt { get; set; }
public int? StatusId { get; set; }
public string Status { get; set; }
public int? PropertyId { get; set; }
public int? AssignedToId { get; set; }
public string AssignedTo { get; set; }
public string Comments { get; set; }
public DateTime? AddedAt { get; set; }
public DateTime? ModifiedAt { get; set; }
}
I am unable to replicate this behavior. I updated and used the following sample code, that includes the GROUP_CONCAT aggregate function that you mentioned in your comment, which works without issues in Pomelo 5.0.0-alpha.2:
using System.Diagnostics;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using MySqlConnector;
using Pomelo.EntityFrameworkCore.MySql.Infrastructure;
namespace IssueConsoleTemplate
{
public class IceCream
{
public int IceCreamId { get; set; }
public string Name { get; set; }
public string Company { get; set; }
public string FullName { get; set; }
}
public class Context : DbContext
{
public virtual DbSet<IceCream> IceCreams { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var connectionString = "server=127.0.0.1;port=3306;user=root;password=;database=So65847111_GroupConcat";
optionsBuilder.UseMySql(
connectionString,
ServerVersion.AutoDetect(connectionString),
options => options.CharSetBehavior(CharSetBehavior.NeverAppend))
.UseLoggerFactory(
LoggerFactory.Create(
configure => configure
.AddConsole()
.AddFilter(level => level >= LogLevel.Information)))
.EnableSensitiveDataLogging()
.EnableDetailedErrors();
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<IceCream>(
entity =>
{
entity.Property(e => e.Name)
.HasDefaultValue("Vanilla");
entity.HasData(
new IceCream {IceCreamId = 1, Name = "Vanilla", Company = "Icecold"},
new IceCream {IceCreamId = 2, Name = "Chocolate", Company = "Mr IceCream"});
});
}
}
internal static class Program
{
private static void Main(string[] args)
{
using var context = new Context();
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
var iceCreamIdParameter = new MySqlParameter
{
ParameterName = "#iceCreamIdParam",
MySqlDbType = MySqlDbType.Int32,
Direction = System.Data.ParameterDirection.Input,
Value = 42, // <-- does not exist
};
var iceCreams = context.IceCreams
.FromSqlRaw(#"
SELECT `IceCreamId`, `Name`, `Company`, GROUP_CONCAT(`Name`, `Company` SEPARATOR ', ') AS `FullName`
FROM `IceCreams`
WHERE `IceCreamId` = #iceCreamIdParam
GROUP BY `IceCreamId`, `Name`, `Company`", iceCreamIdParameter)
.AsNoTracking()
.ToList();
Trace.Assert(iceCreams.Count == 0);
}
}
}
So to help you, we need more information:
The the exact LINQ query (including the exact SQL query you use in your FromSqlRaw() call)
The database server type (e.g. MySQL or MariaDB) and its exact version (e.g. 8.0.21)
(Just update the OP with the requested information.)
The exception hints, that one of your returned fields does not contain the type (or nullability) that it should:
System.InvalidCastException: Specified cast is not valid.
at MySqlConnector.Core.Row.GetInt32(Int32 ordinal)
So your query expects an Int32, but the returned value is something else.
Let your debugger break when the exception is thrown in Row.GetInt32() and examine the value it tries to cast to Int32. Then examine the ordinal parameter of the method. Finally, check the expression at the same position as the ordinal parameter in the SQL query that EF Core generated (you should find it in the Command.CommandText property of the MySqlDataReader object in the stack, or you can just log it with EF Core).
In addition to that, you can run the code I posted on your server. It should work flawlessly. If it doesn't, than this should be related to some unexpected MySQL server setting.
I have a class department inheriting from activeentity
public class ActiveEntity : Entity, IActive
{
public ActiveEntity()
{
IsActive = true;
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid Id { get; set; }
public bool IsActive { get; set; }
[Timestamp, ScaffoldColumn(false), DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Computed)]
public Byte[] Timestamp { get; set; }
[ScaffoldColumn(false)]
public string CreationUserId { get; set; }
[ScaffoldColumn(false)]
public string LastModifiedUserId { get; set; }
}
public class Department:ActiveEntity
{
public Department()
{
this.Address = new DepartmentAddress();
}
[StringLength(9),MinLength(9),MaxLength(9)]
public string Name { get; set; }
public Guid ManagerId { get; set; }
[UIHint("AjaxDropdown")]
public User Manager { get; set; }
public Guid? AddressId { get; set; }
public DepartmentAddress Address { get; set; }
public ICollection<OverheadRate> OverheadRates { get; set; }
}
I am just using annotations no Fluent API. The data saves to the data Sql Server 2008 just fine however the address object never gets instantiated, even though I have the context use the include
return c.Set<Department>().Include(d => d.Address).Include(d => d.Manager).Where(predicate);
The data is returned I run sql profiler and then run the query it returns the correct data.
Any thoughts or suggestions?
Remove instantiating the address (this.Address = new DepartmentAddress();) in the Department constructor. Instantiating navigation references in the default constructor is evil and has nasty side effects like these:
What would cause the Entity Framework to save an unloaded (but lazy loadable) reference over existing data?
EF 4.1 Code First: Why is EF not setting this navigation property?
I keep getting this error when i run my MVC application. The app builds fine but throws this error on the runtime.
Here is the scenario.
[DisplayColumn("Name", "Name", false)]
public partial class ApplicationAction
{
public Guid ApplicationActionId { get; set; }
[Required, StringLength(150), Column("ActionName")]
public string Action { get; set; }
[Required, StringLength(150)]
public string Controller { get; set; }
[StringLength(150)]
public string Area { get; set; }
[StringLength(250)]
public string Description { get; set; }
//Navigation Properties
public virtual ICollection<ApplicationActionGroup> ApplicationActionGroups { get; set; }
public ApplicationAction()
{
ApplicationActionId = Guid.NewGuid();
}
}
public DbSet<ApplicationAction> ApplicationActions { get; set; }
public static ApplicationAction GetAction(string actionName, string controller, string area, IEnumerable<ApplicationAction> actions)
{
foreach (ApplicationAction a in actions)
{
if (a.Action.Equals(actionName, StringComparison.InvariantCultureIgnoreCase)
&& a.Controller.Equals(controller, StringComparison.InvariantCultureIgnoreCase)
&& (
(string.IsNullOrEmpty(a.Area) && string.IsNullOrEmpty(area)) ||
(!string.IsNullOrEmpty(a.Area) && a.Area.Equals(area, StringComparison.InvariantCultureIgnoreCase))
)
)
{
return a;
}
}
return null;
}
I get an error on GetAction method. It comes up as Invalid object name 'dbo.ApplicationAction'. The sql database, there is a table called ApplicationActions. Not sure whats causing this error.
are you sure that [DisplayColumn("Name", "Name", false)]
is a valid attribute for a class?