I'm saving an item in MongoDB using the C# driver V2.9.3.
I'm seeing the following exception being thrown occasionally (although once its happened once it appears to be more lightly to happen again).
System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
at System.Collections.Generic.Dictionary`2.Enumerator.MoveNext()
at MongoDB.Bson.Serialization.Serializers.DictionarySerializerBase`3.SerializeDocumentRepresentation(BsonSerializationContext context, TDictionary value)
at MongoDB.Bson.Serialization.Serializers.ClassSerializerBase`1.Serialize(BsonSerializationContext context, BsonSerializationArgs args, TValue value)
at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Serialize(IBsonSerializer serializer, BsonSerializationContext context, Object value)
at MongoDB.Bson.Serialization.BsonClassMapSerializer`1.SerializeClass(BsonSerializationContext context, BsonSerializationArgs args, TClass document)
at MongoDB.Bson.Serialization.BsonClassMapSerializer`1.Serialize(BsonSerializationContext context, BsonSerializationArgs args, TClass value)
at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Serialize(IBsonSerializer serializer, BsonSerializationContext context, Object value)
at MongoDB.Bson.Serialization.Serializers.BsonValueSerializerBase`1.Serialize(BsonSerializationContext context, BsonSerializationArgs args, TBsonValue value)
at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Serialize(IBsonSerializer serializer, BsonSerializationContext context, Object value)
at MongoDB.Bson.Serialization.Serializers.BsonValueSerializerBase`1.Serialize(BsonSerializationContext context, BsonSerializationArgs args, TBsonValue value)
at MongoDB.Driver.Core.WireProtocol.Messages.Encoders.BinaryEncoders.CommandMessageBinaryEncoder.WriteType1Section(BsonBinaryWriter writer, Type1CommandMessageSection section, Int64 messageStartPosition)
at MongoDB.Driver.Core.WireProtocol.Messages.Encoders.BinaryEncoders.CommandMessageBinaryEncoder.WriteSections(BsonBinaryWriter writer, IEnumerable`1 sections, Int64 messageStartPosition)
at MongoDB.Driver.Core.WireProtocol.Messages.Encoders.BinaryEncoders.CommandMessageBinaryEncoder.WriteMessage(CommandMessage message)
at MongoDB.Driver.Core.Connections.BinaryConnection.SendMessagesHelper.EncodeMessages(CancellationToken cancellationToken, List`1& sentMessages)
at MongoDB.Driver.Core.Connections.BinaryConnection.SendMessagesAsync(IEnumerable`1 messages, MessageEncoderSettings messageEncoderSettings, CancellationToken cancellationToken)
at MongoDB.Driver.Core.WireProtocol.CommandUsingCommandMessageWireProtocol`1.ExecuteAsync(IConnection connection, CancellationToken cancellationToken)
at MongoDB.Driver.Core.Servers.Server.ServerChannel.ExecuteProtocolAsync[TResult](IWireProtocol`1 protocol, CancellationToken cancellationToken)
at MongoDB.Driver.Core.Operations.RetryableWriteOperationExecutor.ExecuteAsync[TResult](IRetryableWriteOperation`1 operation, RetryableWriteContext context, CancellationToken cancellationToken)
at MongoDB.Driver.Core.Operations.BulkUnmixedWriteOperationBase`1.ExecuteBatchAsync(RetryableWriteContext context, Batch batch, CancellationToken cancellationToken)
at MongoDB.Driver.Core.Operations.BulkUnmixedWriteOperationBase`1.ExecuteBatchesAsync(RetryableWriteContext context, CancellationToken cancellationToken)
at MongoDB.Driver.Core.Operations.BulkMixedWriteOperation.ExecuteBatchAsync(RetryableWriteContext context, Batch batch, CancellationToken cancellationToken)
at MongoDB.Driver.Core.Operations.BulkMixedWriteOperation.ExecuteAsync(IWriteBinding binding, CancellationToken cancellationToken)
at MongoDB.Driver.OperationExecutor.ExecuteWriteOperationAsync[TResult](IWriteBinding binding, IWriteOperation`1 operation, CancellationToken cancellationToken)
at MongoDB.Driver.MongoCollectionImpl`1.ExecuteWriteOperationAsync[TResult](IClientSessionHandle session, IWriteOperation`1 operation, CancellationToken cancellationToken)
at MongoDB.Driver.MongoCollectionImpl`1.BulkWriteAsync(IClientSessionHandle session, IEnumerable`1 requests, BulkWriteOptions options, CancellationToken cancellationToken)
at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSessionAsync[TResult](Func`2 funcAsync, CancellationToken cancellationToken)
at MongoDB.Driver.MongoCollectionBase`1.InsertOneAsync(TDocument document, InsertOneOptions options, Func`3 bulkWriteAsync)
at MyApp.Program.MongoDbResultSaver.Save(PhishingResult result, IEmailHolder email) line 107
at MyApp.Program.Services.MongoDbResultSaver.Save(PhishingResult result, IEmailHolder email) line 121
See below for my redacted code
try
{
var obj= new MyDbObject()
{
ID = Guid.NewGuid().ToString(),
// meny propertys including objects, and lists of objects
};
var metaCollection = db.GetCollection<MyDbObject>("MyDbObject");
await metaCollection.InsertOneAsync(obj);
_logger.Info("Saved with ID " + obj.ID);//line 107 in stack trace where the error is coming from
}
catch (Exception e)
{
_logger.Error($"Failed to save metastore with error {e}");
throw;//line 121 in stacktrace where the error is being rethrown
}
And relevant part of object definition
[BsonIgnoreExtraElements]
public class MyDbObject
{
[BsonId]
public string ID { get; set; }
[BsonElement("etc")]
//etc
}
Any help is appreciated, we have only observed this happening in production with mongodb atlas M10 instance as the server.
You can use ObjectId for unique identifier of document.
try
{
var obj= new MyDbObject()
{
ID = ObjectId.GenerateNewId(),
// many properties including objects, and lists of objects
};
var metaCollection = db.GetCollection<MyDbObject>("MyDbObject");
await metaCollection.InsertOneAsync(obj);
_logger.Info("Saved with ID " + obj.ID);//line 107 in stack trace where the error is coming from
}
catch (Exception e)
{
_logger.Error($"Failed to save metastore with error {e}");
throw;//line 121 in stacktrace where the error is being rethrown
}
Object model will be,
[BsonIgnoreExtraElements]
public class MyDbObject
{
[BsonId]
public ObjectId ID { get; set; }
[BsonElement("etc")]
//etc
}
Turns out the issue is that I had a task that had timed out with a reference to the object I was saving, it happened to complete and add an item to the a dictionary property at the same time the item was saving in Mogo.
Related
I currently have a problem with EF6 and Fluent API. When inserting into database where model have one to many relationship, I'm getting this error. I've checked some related topics, but I want to keep autoincrement. Model without one to many relationship works perfectly.
Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while saving the entity changes. See the inner exception for details.
---> Microsoft.Data.SqlClient.SqlException (0x80131904): Cannot insert explicit value for identity column in table 'Roles' when IDENTITY_INSERT is set to OFF.
at Microsoft.Data.SqlClient.SqlCommand.<>c.<ExecuteDbDataReaderAsync>b__188_0(Task`1 result)
at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
at System.Threading.Tasks.Task.<>c.<.cctor>b__272_0(Object obj)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
ClientConnectionId:501a6880-e298-43d5-be69-fcbebacdb15e
Error Number:544,State:1,Class:16
--- End of inner exception stack trace ---
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(StateManager stateManager, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at WorkIT_Backend.Services.UserService.Create(String username, String password, String role) in C:\Users\Ondřej\Desktop\škola\2022 PRF\WS\OPR3\WorkIT_Backend\WorkIT_Backend\WorkIT_Backend\Services\UserService.cs:line 54
at WorkIT_Backend.Controllers.UsersController.CreateUser(UserDto user) in C:\Users\Ondřej\Desktop\škola\2022 PRF\WS\OPR3\WorkIT_Backend\WorkIT_Backend\WorkIT_Backend\Controllers\UsersController.cs:line 57
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
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|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.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)
Model classes
public sealed class Role
{
public long RoleId { get; set; }
public string? Name { get; set; }
public ICollection<User> Users { get; set; }
public Role()
{
Users = new HashSet<User>();
}
}
public class User
{
public long UserId { get; set; }
public string? UserName { get; set; }
public string? PasswordHash { get; set; }
public long RoleId { get; set; }
public virtual Role Role { get; set; }
public User()
{
}
}
OnModelCreating in dbcontext
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Role>(entity =>
{
entity.HasKey(q => q.RoleId);
entity.Property(q => q.RoleId)
.ValueGeneratedOnAdd();
entity.Property(q => q.Name)
.IsRequired();
entity.HasIndex(q => q.Name)
.IsUnique();
});
modelBuilder.Entity<User>(entity =>
{
entity.HasKey(q => q.UserId);
entity.Property(q => q.UserId)
.ValueGeneratedOnAdd();
entity.Property(q => q.UserName)
.IsRequired();
entity.Property(q => q.PasswordHash)
.IsRequired();
entity.HasOne(u => u.Role)
.WithMany(r => r.Users)
.HasForeignKey(u => u.RoleId)
.OnDelete(DeleteBehavior.ClientSetNull);
});
}
Method in service which is adding the user
public async Task<User> Create(string username, string password, string role)
{
EnsureNotNull(username, nameof(username));
EnsureNotNull(password, nameof(password));
EnsureNotNull(role, nameof(role));
username = username.ToLower();
if (_context.Users.Any(q => q.UserName == username))
throw CreateException($"User {username} already exists.", null);
var hash = _securityService.HashPassword(password);
var userRole = await _roleService.GetRole(role);
var ret = new User {UserName = username, PasswordHash = hash, Role = userRole};
_context.Users.Add(ret);
await _context.SaveChangesAsync();
return ret;
}
This method for adding roles works perfectly
public class RoleService
{
private readonly WorkItDbContext _context;
private readonly SecurityService _securityService;
public RoleService(WorkItDbContext context, SecurityService securityService)
{
_context = context;
_securityService = securityService;
}
public async Task<Role> Create(string name)
{
EnsureNotNull(name, nameof(name));
name = name.ToLower();
if (_context.Roles.Any(q => q.Name == name))
throw CreateException($"Role {name} already exists.", null);
var ret = new Role {Name = name};
_context.Add(ret);
await _context.SaveChangesAsync();
return ret;
}
public async Task<List<Role>> GetRoles()
{
var roles = await _context.Roles.ToListAsync();
return roles;
}
public async Task<Role> GetRole(string name)
{
var role = await _context.Roles.FirstAsync(q => q.Name == name) ??
throw CreateException($"Role {name} does not exist.");
return role;
}
}
Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<IConfiguration>(builder.Configuration);
SecurityService securityService = new(builder.Configuration);
builder.Services.AddTransient<WorkItDbContext>();
builder.Services.AddSingleton<SecurityService>();
builder.Services.AddTransient<UserService>();
builder.Services.AddTransient<RoleService>();
I've different combination of dbcontext methods. I tried auto increment through anotation - identity. I've checked SQL server and autoincrement is alright.
Change
builder.Services.AddTransient<WorkItDbContext>();
to
builder.Services.AddDbContext<WorkItDbContext>();
and then your UserService and RoleService will share a WorkItDbContext, because it will be added as a Scoped service. See DbContext in dependency injection for ASP.NET Core
After an update of Visual Studio 2022 to v17.2.2, I suddenly get an error in my ASP.NET app, that a virtual class cannot insert into SQL database because the class does not allow nulls. Before the update I was not getting this error.
This is the model a use
public class Member
{
public int MemberId { get; set; }
[Required(ErrorMessage = "Dit is een verplicht veld")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Dit is een verplicht veld")]
public string LastName { get; set; }
public string MemberImage { get; set; }
public Gender Gender { get; set; }
public int TeamId { get; set; }
public virtual Team Team { get; set; } = new();
}
I need the last virtual property to get all members from the database of a the Team model from the MemberRepository
public async Task<IEnumerable<Member>> GetAllMembersByTeamId(int TeamId)
{
var result = await dbContext.Members
.Include(t => t.Team)
.Where(t => t.TeamId == TeamId)
.ToListAsync();
if (result != null)
{
return result;
}
else
return null;
}
And with the a MemberRepository I store it into the database:
public class MemberRepository : IMemberRepository
{
private readonly AppDbContext dbContext;
public MemberRepository(AppDbContext dbContext)
{
this.dbContext = dbContext;
}
public async Task<Member> AddMember(Member obj)
{
await dbContext.Members.AddAsync(obj);
await dbContext.SaveChangesAsync();
return obj;
}
}
I ask for the team I want to add the member with:
protected async override Task OnInitializedAsync()
{
Team = await TeamsRepository.GetTeamById(int.Parse(Id));
}
and fired it up with the EditForm, OnValidSubmit.
public async Task HandleValidSubmit()
{
ConfirmationTitle = StaticString.ConfirmationTitle;
ConfirmationMessage = StaticString.ConfirmationMessage;
Member.TeamId = int.Parse(Id);
await MemberRepository.AddMember(Member);
NavigationManager.NavigateTo("/adminpage");
}
I'm confused, is it because the update or is something else, because I get the error also now in the previous made ASP.NET application.
Why this approach? I learned it of Kudvenkat from this site: https://www.pragimtech.com/blog/blazor/blazor-model-classes/
This is the error:
Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
This is the error i get:
blazor.server.js:1 [2022-06-02T13:13:22.000Z] Error: Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while saving the entity changes. See the inner exception for details.
---> Microsoft.Data.SqlClient.SqlException (0x80131904): Cannot insert the value NULL into column 'Class', table 'Tjoba-Server.dbo.Teams'; column does not allow nulls. INSERT fails.
The statement has been terminated.
The statement has been terminated.
at Microsoft.Data.SqlClient.SqlCommand.<>c.b__188_0(Task1 result) at System.Threading.Tasks.ContinuationResultTaskFromResultTask2.InnerInvoke()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
ClientConnectionId:2df86c5d-9cee-4c70-ad12-ebb86a036fe9
Error Number:515,State:2,Class:16
--- End of inner exception stack trace ---
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList1 entriesToSave, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(StateManager stateManager, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func4 operation, Func4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at DataAcces.Data.MemberRepository.AddMember(Member obj) in C:\VsProjects\Tjoba_Server\DataAccess\Data\MemberRepository.cs:line 21
at Tjoba.Pages.Admin.AddMember.HandleValidSubmit() in C:\VsProjects\Tjoba_Server\Tjoba\Pages\Admin\AddMember.razor:line 207
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at Microsoft.AspNetCore.Components.Forms.EditForm.HandleSubmitAsync()
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
log # blazor.server.js:1
blazor.server.js:1 [2022-06-02T13:13:22.001Z] Information: Connection disconnected.
Uncaught (in promise) Error: Cannot send data if the connection is not in the 'Connected' State.
at bt.send (blazor.server.js:1:52004)
at kt._sendMessage (blazor.server.js:1:68639)
at kt._sendWithProtocol (blazor.server.js:1:68680)
at kt.send (blazor.server.js:1:68788)
at Object.beginInvokeDotNetFromJS (blazor.server.js:1:131279)
at w (blazor.server.js:1:2164)
at C.invokeMethodAsync (blazor.server.js:1:4014)
at blazor.server.js:1:11516
at T (blazor.server.js:1:11694)
at I (blazor.server.js:1:11485)
I get with a try catch block the same error message
Cannot insert the value NULL into column 'Class', table 'TjobaServer.dbo.Teams'; column does not allow nulls. INSERT fails. The statement has been terminated.
Strange is that I only want to insert a member to the database with a TeamId, but nothing to the table Teams.
I figured out and found the solution.
Have added an if block with the Entity unchanged code into the AddMember Task in the MemberRepository:
public async Task<Member> AddMember(Member member)
{
if (member.Team != null)
{
dbContext.Entry(member.Team).State = EntityState.Unchanged;
}
var result = await dbContext.Memberss.AddAsync(member);
await dbContext.SaveChangesAsync();
return result.Entity;
}
I am storing trees of nodes in a (local) Mongo database, using GUIDs as the EntityId and ParentEntityId for each node. I am trying to retrieve nodes using IAggregateFluentExtensions.GraphLookup(). The call to GraphLookup() is throwing:
MongoDB.Bson.BsonSerializationException : GuidSerializer cannot deserialize a Guid when GuidRepresentation is Unspecified.
Why is it throwing this exception? GUID handling is configured for V3, per the code below. It has been working for storing & retrieving other types in the same database that have GUIDs on them.
Here is my Entity class for each Node:
public class TestEntity
{
[BsonId]
public ObjectId Id { get; set;}
[BsonGuidRepresentation(GuidRepresentation.Standard)]
public Guid EntityId { get; set; }
[BsonGuidRepresentation(GuidRepresentation.Standard)]
public Guid ParentEntityId { get; set; }
public string Name { get; set; }
}
Here is a simplified version of the repository code, which throws the exception, on the GraphLookup() line.
public async Task<List<object>> DoGraphLookup()
{
BsonDefaults.GuidRepresentationMode = GuidRepresentationMode.V3;
BsonSerializer.RegisterSerializer(new GuidSerializer(GuidRepresentation.Standard));
MongoClientSettings mongoClientSettings = MongoClientSettings.FromConnectionString("mongodb://HOSTNAME:27017");
MongoClient mongoClient = new MongoClient(mongoClientSettings);
IMongoDatabase database = mongoClient.GetDatabase("DATABASENAME");
IMongoCollection<TestEntity> collection = database.GetCollection<TestEntity>("COLLECTIONNAME");
List<object> result = await collection
.Aggregate()
//.Match(c => c.Name == "MatchName")
.GraphLookup<TestEntity, Guid, Guid, Guid, TestEntity, IEnumerable<TestEntity>, object>(
from: collection,
startWith: $"${nameof(TestEntity.EntityId)}",
connectFromField: nameof(TestEntity.ParentEntityId),
connectToField: nameof(TestEntity.EntityId),
#as: "BreadCrumb",
depthField: "order")
.ToListAsync();
return result;
}
I'm using C# .NET Core 3.1, with these Nuget packages in my project:
MongoDB.Bson 2.13.1
MongoDB.Driver 2.13.1
MongoDB.Driver.Core 2.13.1
DB Looks like this:
Database contents
--- EDIT ---
Exception stack trace:
MyApplication.Repositories.TreeOfNodesRepository.DoGraphLookup:
Outcome: Failed
Error Message:
MongoDB.Bson.BsonSerializationException : GuidSerializer cannot deserialize a Guid when GuidRepresentation is Unspecified.
Stack Trace:
at MongoDB.Bson.Serialization.Serializers.GuidSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize[TValue](IBsonSerializer1 serializer, BsonDeserializationContext context) at MongoDB.Bson.Serialization.Serializers.ObjectSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize[TValue](IBsonSerializer1 serializer, BsonDeserializationContext context)
at MongoDB.Bson.Serialization.Serializers.DynamicDocumentBaseSerializer1.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) at MongoDB.Bson.Serialization.Serializers.SerializerBase1.MongoDB.Bson.Serialization.IBsonSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
at MongoDB.Bson.Serialization.Serializers.ObjectSerializer.DeserializeDiscriminatedValue(BsonDeserializationContext context, BsonDeserializationArgs args)
at MongoDB.Bson.Serialization.Serializers.ObjectSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize[TValue](IBsonSerializer1 serializer, BsonDeserializationContext context) at MongoDB.Bson.Serialization.Serializers.EnumerableSerializerBase2.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize[TValue](IBsonSerializer1 serializer, BsonDeserializationContext context) at MongoDB.Driver.Core.Operations.AggregateOperation1.CursorDeserializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize[TValue](IBsonSerializer1 serializer, BsonDeserializationContext context) at MongoDB.Driver.Core.Operations.AggregateOperation1.AggregateResultDeserializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize[TValue](IBsonSerializer1 serializer, BsonDeserializationContext context) at MongoDB.Driver.Core.WireProtocol.CommandUsingCommandMessageWireProtocol1.ProcessResponse(ConnectionId connectionId, CommandMessage responseMessage)
at MongoDB.Driver.Core.WireProtocol.CommandUsingCommandMessageWireProtocol1.ExecuteAsync(IConnection connection, CancellationToken cancellationToken) at MongoDB.Driver.Core.Servers.Server.ServerChannel.ExecuteProtocolAsync[TResult](IWireProtocol1 protocol, ICoreSession session, CancellationToken cancellationToken)
at MongoDB.Driver.Core.Operations.RetryableReadOperationExecutor.ExecuteAsync[TResult](IRetryableReadOperation1 operation, RetryableReadContext context, CancellationToken cancellationToken) at MongoDB.Driver.Core.Operations.ReadCommandOperation1.ExecuteAsync(RetryableReadContext context, CancellationToken cancellationToken)
at MongoDB.Driver.Core.Operations.AggregateOperation1.ExecuteAsync(RetryableReadContext context, CancellationToken cancellationToken) at MongoDB.Driver.Core.Operations.AggregateOperation1.ExecuteAsync(IReadBinding binding, CancellationToken cancellationToken)
at MongoDB.Driver.OperationExecutor.ExecuteReadOperationAsync[TResult](IReadBinding binding, IReadOperation1 operation, CancellationToken cancellationToken) at MongoDB.Driver.MongoCollectionImpl1.ExecuteReadOperationAsync[TResult](IClientSessionHandle session, IReadOperation1 operation, ReadPreference readPreference, CancellationToken cancellationToken) at MongoDB.Driver.MongoCollectionImpl1.AggregateAsync[TResult](IClientSessionHandle session, PipelineDefinition2 pipeline, AggregateOptions options, CancellationToken cancellationToken) at MongoDB.Driver.MongoCollectionImpl1.UsingImplicitSessionAsync[TResult](Func2 funcAsync, CancellationToken cancellationToken) at MongoDB.Driver.IAsyncCursorSourceExtensions.ToListAsync[TDocument](IAsyncCursorSource1 source, CancellationToken cancellationToken)
at MyApplication.Repositories.TreeOfNodesRepository.DoGraphLookup() in c:\Source\saasem\CodeGenerator\Tests\CodeGenerator.ApplicationStore.Tests\Repositories\GraphcLookupTest.cs:line 45
at NUnit.Framework.Internal.TaskAwaitAdapter.GenericAdapter1.BlockUntilCompleted() at NUnit.Framework.Internal.MessagePumpStrategy.NoMessagePumpStrategy.WaitForCompletion(AwaitAdapter awaiter) at NUnit.Framework.Internal.AsyncToSyncAdapter.Await(Func1 invoke)
at NUnit.Framework.Internal.Commands.TestMethodCommand.RunTestMethod(TestExecutionContext context)
at NUnit.Framework.Internal.Commands.TestMethodCommand.Execute(TestExecutionContext context)
at NUnit.Framework.Internal.Execution.SimpleWorkItem.<>c__DisplayClass4_0.b__0()
at NUnit.Framework.Internal.ContextUtils.<>c__DisplayClass1_01.<DoIsolated>b__0(Object _) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) --- End of stack trace from previous location --- at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at NUnit.Framework.Internal.ContextUtils.DoIsolated(ContextCallback callback, Object state) at NUnit.Framework.Internal.ContextUtils.DoIsolated[T](Func1 func)
at NUnit.Framework.Internal.Execution.SimpleWorkItem.PerformWork()
I have my model:
public class Membership
{
[Key]
[Required]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[MinLength(3)]
[MaxLength(30)]
public string Name { get; set; }
[Required] public int PeriodType { get; set; }
[Required] public int Duration { get; set; }
[Required] public int TerminationPeriod { get; set; }
[Required] public float InstallmentPrice { get; set; }
}
And my Dto:
public class MembershipDto
{
public int Id { get; private set; }
public string Name { get; set; }
public int PeriodType { get; set; }
public int Duration { get; set; }
public int TerminationPeriod { get; set; }
public float InstallmentPrice { get; set; }
}
I'm using Entity Framework and JsonPatchDocument to make PATCH operation in my API, the code is following:
public async Task<MembershipDto> Handle(EditMembershipCommand request, CancellationToken cancellationToken)
{
var membershipEntity = await _dbContext
.Memberships
.SingleOrDefaultAsync(m => m.Id == request.Id);
if (membershipEntity is null)
throw new NullReferenceException($"Membership [Id: {request.Id}] not found");
var editedMembership = request.NewMembershipDto.Adapt<JsonPatchDocument<Membership>>(); //request.NewMembershipDto is type of JsonPatchDocument<MembershipDto>
editedMembership.ApplyTo(membershipEntity, ModelState);
_ = await _dbContext.SaveChangesAsync();
var membershipDto = editedMembership.Adapt<MembershipDto>();
return membershipDto;
}
As an output I get the following information:
ProblemDetails.ProblemDetailsMiddleware[1]
An unhandled exception has occurred while executing the request.
Mapster.CompileException: Error while compiling
source=Microsoft.AspNetCore.JsonPatch.JsonPatchDocument`1[AgreementApi.Dtos.MembershipDto]
destination=Microsoft.AspNetCore.JsonPatch.JsonPatchDocument`1[AgreementApi.Models.Membership]
type=Map
---> Mapster.CompileException: Error while compiling
source=Newtonsoft.Json.Serialization.IContractResolver
destination=Newtonsoft.Json.Serialization.IContractResolver
type=Map
---> System.InvalidOperationException: No default constructor for type 'IContractResolver', please use 'ConstructUsing' or 'MapWith'
at Mapster.Utils.DynamicTypeGenerator.CreateTypeForInterface(Type interfaceType)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at Mapster.Utils.DynamicTypeGenerator.GetTypeForInterface(Type interfaceType)
at Mapster.Adapters.RecordTypeAdapter.CreateInstantiationExpression(Expression source, Expression destination, CompileArgument arg)
at Mapster.Adapters.BaseAdapter.CreateInstantiationExpression(Expression source, CompileArgument arg)
at Mapster.Adapters.RecordTypeAdapter.CreateInlineExpression(Expression source, CompileArgument arg)
at Mapster.Adapters.BaseAdapter.CreateInlineExpressionBody(Expression source, CompileArgument arg)
at Mapster.Adapters.BaseAdapter.CreateExpressionBody(Expression source, Expression destination, CompileArgument arg)
at Mapster.Adapters.BaseAdapter.CreateAdaptFunc(CompileArgument arg)
at Mapster.TypeAdapterConfig.CreateMapExpression(CompileArgument arg)
--- End of inner exception stack trace ---
at Mapster.TypeAdapterConfig.CreateMapExpression(CompileArgument arg)
at Mapster.TypeAdapterConfig.CreateInlineMapExpression(Type sourceType, Type destinationType, MapType mapType, CompileContext context, MemberMapping mapping)
at Mapster.Adapters.BaseAdapter.CreateAdaptExpressionCore(Expression source, Type destinationType, CompileArgument arg, MemberMapping mapping, Expression destination)
at Mapster.Adapters.BaseAdapter.CreateAdaptExpression(Expression source, Type destinationType, CompileArgument arg, MemberMapping mapping, Expression destination)
at Mapster.Adapters.ClassAdapter.CreateInlineExpression(Expression source, CompileArgument arg)
at Mapster.Adapters.BaseAdapter.CreateInlineExpressionBody(Expression source, CompileArgument arg)
at Mapster.Adapters.BaseAdapter.CreateExpressionBody(Expression source, Expression destination, CompileArgument arg)
at Mapster.Adapters.BaseAdapter.CreateAdaptFunc(CompileArgument arg)
at Mapster.TypeAdapterConfig.CreateMapExpression(CompileArgument arg)
--- End of inner exception stack trace ---
at Mapster.TypeAdapterConfig.CreateMapExpression(CompileArgument arg)
at Mapster.TypeAdapterConfig.CreateMapExpression(TypeTuple tuple, MapType mapType)
at Mapster.TypeAdapterConfig.CreateDynamicMapExpression(TypeTuple tuple)
at Mapster.TypeAdapterConfig.<GetDynamicMapFunction>b__66_0[TDestination](TypeTuple tuple)
at Mapster.TypeAdapterConfig.<>c__DisplayClass55_0`1.<AddToHash>b__0(TypeTuple types)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at Mapster.TypeAdapterConfig.AddToHash[T](ConcurrentDictionary`2 hash, TypeTuple key, Func`2 func)
at Mapster.TypeAdapterConfig.GetDynamicMapFunction[TDestination](Type sourceType)
at Mapster.TypeAdapter.Adapt[TDestination](Object source, TypeAdapterConfig config)
at Mapster.TypeAdapter.Adapt[TDestination](Object source)
at Fitverse.AgreementApi.Handlers.EditMembershipHandler.Handle(EditMembershipCommand request, CancellationToken cancellationToken) in /Users/wonsu/Repositories/Fitverse/Fitverse.AgreementApi/Handlers/EditMembershipHandler.cs:line 34
at MediatR.Pipeline.RequestExceptionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at MediatR.Pipeline.RequestExceptionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at MediatR.Pipeline.RequestPostProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at MediatR.Pipeline.RequestPreProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at Fitverse.AgreementApi.Controllers.SettingsController.EditMembership(Int32 id, JsonPatchDocument`1 membershipDto) in /Users/wonsu/Repositories/Fitverse/Fitverse.AgreementApi/Controllers/SettingsController.cs:line 52
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
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__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Hellang.Middleware.ProblemDetails.ProblemDetailsMiddleware.Invoke(HttpContext context)
I know that the issue is in this line of code:
var editedMembership = request.NewMembershipDto.Adapt<JsonPatchDocument<Membership>>();
But I don't know how to change it to properly map it to desired type. Could you help me? :)
I know that at the end I should probably get the membership from DB again, map it and return it instead of just mapping editedMembership, but I'll fit it after dealing with this mapping issue.
Add the mapping of IContractResolver helps resolve the issue.
private static TypeAdapterConfig GetConfiguredMappingConfig()
{
var config = TypeAdapterConfig.GlobalSettings;
IList<IRegister> registers = config.Scan(Assembly.GetExecutingAssembly());
config.Apply(registers);
config.NewConfig<IContractResolver, IContractResolver>()
.ConstructUsing(src => new DefaultContractResolver());
return config;
}
I have a problem with the post method in my register.service.ts as it should return 200 OK, but instead, it returns 405 method not allowed. I am struggling with this error for some time and I know it because I have to allow it in the header configuration and CORS middleware. I have created a middleware class which I pass it in startup.cs along with other CORS configuration as follows:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<DataContext>(options => options.UseMySql(Configuration.GetConnectionString("DataContext")));
services.AddControllersWithViews();
services.AddApiVersioning(options =>
{
options.UseApiBehavior = false;
options.AssumeDefaultVersionWhenUnspecified = true;
});
services.AddCors(options =>
{
options.AddPolicy(MyAllowSpecificOrigins,
builder => builder.WithOrigins("http://localhost:5001").AllowAnyHeader().AllowAnyMethod());
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist/";
});
});
services.AddScoped(typeof(IUserService<>), typeof(UserService<>));
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
if (!env.IsDevelopment())
{
app.UseSpaStaticFiles();
}
app.UseOptions();//this is the method from the CORS middleware class
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
}
}
This is the register.service.ts:
import { Injectable } from '#angular/core';
import { HttpClient, HttpClientModule, HttpHeaders } from '#angular/common/http';
import { environment } from 'src/environments/environment'; import { Register } from '../Models/register';
import { Observable, throwError } from 'rxjs';
import { retry, catchError } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class RegisterService {
baseurl = 'https://localhost:5001';
constructor(private http: HttpClient) { }
Create(user): Observable<Register> {
const httpOptions = { headers: new HttpHeaders({ 'Content-Type':
'application/x-www-form-urlencoded', 'Access-Control-Allow-Headers': 'Authorization',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS'})};
return this.http.post<Register>(this.baseurl + '/register', JSON.stringify(user),
httpOptions).pipe(retry(1), catchError(this.errorHandler));
}
GetById(id: number) {
let reqHeader = new HttpHeaders();
return this.http.post(this.baseurl + '/register/' + id , {headers: reqHeader});
}
GetAll() {
let reqHeader = new HttpHeaders();
return this.http.get(this.baseurl + '/register/', {headers: reqHeader});
}
Update(user: Register) {
let reqHeader = new HttpHeaders();
return this.http.post(this.baseurl + '/register/editUser', user, {headers: reqHeader});
}
Delete(id: number) {
let reqHeader = new HttpHeaders();
return this.http.get(this.baseurl + '/register/deleteUser/' + id, {headers: reqHeader});
}
errorHandler(error) {
let errorMessage = '';
if (error.error instanceof ErrorEvent) {
// Get client-side error
errorMessage = error.error.message;
} else {
// Get server-side error
errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
}
console.log(errorMessage);
return throwError(errorMessage);
}
}
I have also replaced the x-www-form-urlencoded with application/json but it has the same behaviour both in the browser and Postman.
This is the RegisterController.cs class:
[EnableCors]
[Produces("application/json")]
[Route("[controller]")]
[ApiController]
public class RegisterController : ControllerBase
{
private readonly DataContext _context;
private readonly IUserService<Register> _repo;
public RegisterController(DataContext context,IUserService<Register> repo)
{
_context = context;
_repo=repo;
}
// GET: api/Register
[HttpGet]
public async Task<ActionResult<IEnumerable<Register>>> Getregistrations()
{
return await _context.register.ToListAsync();
}
// GET: api/Register/5
[HttpGet("{id}")]
public async Task<ActionResult<Register>> GetRegister([FromRoute]int id)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var user = await _context.register.FindAsync(id);
if (user == null)
{
return NotFound();
}
return Ok(user);
}
// PUT: api/Register/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://aka.ms/RazorPagesCRUD.
[HttpPut("{id}")]
public async Task<IActionResult> PutRegister([FromRoute]int id,[FromBody] Register register)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != register.Id)
{
return BadRequest();
}
_context.Entry(register).State = EntityState.Modified;
try
{
_repo.Update(register);
var save = await _repo.SaveAsync(register);
}
catch (DbUpdateConcurrencyException)
{
if (!RegisterExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
// POST: api/Register
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://aka.ms/RazorPagesCRUD.
[Route("PostRegister")]
[HttpPost]
[HttpOptions]
public async Task<ActionResult<Register>> PostRegister([FromBody] Register register)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
_repo.Add(register);
var save = await _repo.SaveAsync(register);
return CreatedAtAction(nameof(GetRegister), new { id = register.Id }, register);
}
// DELETE: api/Register/5
[HttpDelete("{id}")]
public async Task<ActionResult<Register>> DeleteRegister([FromRoute]int id)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var user = await _context.register.FindAsync(id);
if (user == null)
{
return NotFound();
}
_repo.Delete(user);
var save = await _repo.SaveAsync(user);
return Ok(user);
}
private bool RegisterExists(int id)
{
return _context.register.Any(e => e.Id == id);
}
}
I have no idea why it's not working. Can someone please help me figure it out? Please let me know if you need more details.
UPDATE:
I have tried what sam suggested and I get the same result as before:
This is in Postman:
Postman result for POST
And this is from the browser:
Browser result
UPDATE 2: After trying with [FromForm] instead of [FromBody] with application/json as header:
for https://localhost:5001/register get same error 405
for https://localhost:5001/register/PostRegister getting 500
for register/PostRegister
I forgot to specify that my route path is configured to https://localhost:5001/Add
STACKTRACE:
fail: Microsoft.EntityFrameworkCore.Database.Command[20102]
Failed executing DbCommand (53ms) [Parameters=[#p0='?' (Size = 4000), #p1='?' (Size = 4000), #p2='?' (Size = 4000)], CommandType='Text', CommandTimeout='30']
INSERT INTO `register` (`Email`, `Name`, `Password`)
VALUES (#p0, #p1, #p2);
SELECT `Id`
FROM `register`
WHERE ROW_COUNT() = 1 AND `Id` = LAST_INSERT_ID();
fail: Microsoft.EntityFrameworkCore.Update[10000]
An exception occurred in the database while saving changes for context type 'AnotherAP.Helpers.DataContext'.
Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
---> MySql.Data.MySqlClient.MySqlException (0x80004005): Column 'email' cannot be null
---> MySql.Data.MySqlClient.MySqlException (0x80004005): Column 'email' cannot be null
at MySqlConnector.Core.ServerSession.ReceiveReplyAsyncAwaited(ValueTask`1 task) in C:\projects\mysqlconnector\src\MySqlConnector\Core\ServerSession.cs:line 774
at MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) in C:\projects\mysqlconnector\src\MySqlConnector\Core\ResultSet.cs:line 49
at MySql.Data.MySqlClient.MySqlDataReader.ActivateResultSet() in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs:line 130
at MySql.Data.MySqlClient.MySqlDataReader.CreateAsync(CommandListPosition commandListPosition, ICommandPayloadCreator payloadCreator, IDictionary`2 cachedProcedures, IMySqlCommand command, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs:line 391
at MySqlConnector.Core.CommandExecutor.ExecuteReaderAsync(IReadOnlyList`1 commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in C:\projects\mysqlconnector\src\MySqlConnector\Core\CommandExecutor.cs:line 62
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(DbContext _, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
---> MySql.Data.MySqlClient.MySqlException (0x80004005): Column 'email' cannot be null
---> MySql.Data.MySqlClient.MySqlException (0x80004005): Column 'email' cannot be null
at MySqlConnector.Core.ServerSession.ReceiveReplyAsyncAwaited(ValueTask`1 task) in C:\projects\mysqlconnector\src\MySqlConnector\Core\ServerSession.cs:line 774
at MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) in C:\projects\mysqlconnector\src\MySqlConnector\Core\ResultSet.cs:line 49
at MySql.Data.MySqlClient.MySqlDataReader.ActivateResultSet() in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs:line 130
at MySql.Data.MySqlClient.MySqlDataReader.CreateAsync(CommandListPosition commandListPosition, ICommandPayloadCreator payloadCreator, IDictionary`2 cachedProcedures, IMySqlCommand command, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs:line 391
at MySqlConnector.Core.CommandExecutor.ExecuteReaderAsync(IReadOnlyList`1 commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in C:\projects\mysqlconnector\src\MySqlConnector\Core\CommandExecutor.cs:line 62
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(DbContext _, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
---> MySql.Data.MySqlClient.MySqlException (0x80004005): Column 'email' cannot be null
---> MySql.Data.MySqlClient.MySqlException (0x80004005): Column 'email' cannot be null
at MySqlConnector.Core.ServerSession.ReceiveReplyAsyncAwaited(ValueTask`1 task) in C:\projects\mysqlconnector\src\MySqlConnector\Core\ServerSession.cs:line 774
at MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) in C:\projects\mysqlconnector\src\MySqlConnector\Core\ResultSet.cs:line 49
at MySql.Data.MySqlClient.MySqlDataReader.ActivateResultSet() in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs:line 130
at MySql.Data.MySqlClient.MySqlDataReader.CreateAsync(CommandListPosition commandListPosition, ICommandPayloadCreator payloadCreator, IDictionary`2 cachedProcedures, IMySqlCommand command, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs:line 391
at MySqlConnector.Core.CommandExecutor.ExecuteReaderAsync(IReadOnlyList`1 commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in C:\projects\mysqlconnector\src\MySqlConnector\Core\CommandExecutor.cs:line 62
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(DbContext _, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at AnotherAP.Helpers.UserService`1.SaveAsync(T entity) in /Users/Chsyn/Projects/copyofAAP/AnotherAP/Helpers/UserService.cs:line 35
at AnotherAP.Controllers.RegisterController.PostRegister(Register register) in /Users/Chsyn/Projects/copyofAAP/AnotherAP/Controllers/RegisterController.cs:line 110
at lambda_method(Closure , Object )
at Microsoft.Extensions.Internal.ObjectMethodExecutorAwaitable.Awaiter.GetResult()
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
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.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(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__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
This is how my Create() method looks now in register.service.ts:
baseurl = 'https://localhost:5001';
constructor(private http: HttpClient) { }
Create(user): Observable<Register> {
const httpOptions = { headers: new HttpHeaders(
{ 'Content-Type': 'application/json',
'Accept': 'application/json'
})
};
return this.http.post<Register>(this.baseurl + '/register/Add' , JSON.stringify(user),
httpOptions).pipe(retry(1), catchError(this.errorHandler));
}
Could you try modifying httpOptions as below, please post your observations after trying this:
const httpOptions = { headers: new HttpHeaders(
{ 'Content-Type': 'application/json, application/x-www-form-urlencoded',
{ 'Accept': 'application/json, text/plain, */*',
/*'Access-Control-Allow-Headers': 'Authorization',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS'*/
})
};
return this.http.post<Register>(this.baseurl, JSON.stringify(user),
httpOptions).pipe(retry(1), catchError(this.errorHandler));
}