fluent validator in class library not work in asp.net core - asp.net-core

when i put fluent validators in asp.net core client side validation project exactly work
but when i put validator in class library not work
My model and validator in class library :
using FluentValidation;
namespace ClassLibrary1
{
public class Person
{
public string Name { get; set; }
public string Family { get; set; }
public int Age { get; set; }
}
public class PersonValidator : AbstractValidator<Person>
{
public PersonValidator()
{
RuleFor(c => c.Name).NotEmpty().WithMessage("Name Is Empty");
}
}
}
In program.cs file :
services.AddFluentValidationAutoValidation(M =>
{
M.DisableDataAnnotationsValidation = true;
}).AddFluentValidationClientsideAdapters()
.AddValidatorsFromAssemblyContaining<PersonValidator>();

I can't reproduce the issue, and it works in my side, I will show my test steps.
Steps
my project structure.
The person.cs code same as yours
The program.cs code same as yours
My test method in Controller.
[HttpPost]
[Route("Test")]
public IActionResult Test([FromBody]Person model)
{
if (!ModelState.IsValid) //<----Validate here
{
return new BadRequestObjectResult(ModelState);
}
return Ok();
//Other Code..
}
Test result and it works.

I found the solution.
When the class library is nullable, the client-side validation in ASP.NET Core does not work.
Solution:
Remove <Nullable>enable</Nullable> from the *.csproj
Define nullable property:
public string? name{get;set}

Related

ASP.NET Core Web API Error: Model 1[TContext] violates the Constraint of type 'TContext'

I have a Solution in Visual Studio 2017 that contains the following Projects:
CredentialManager.API (ASP.NET Core 2.1 Web API project)
CredentialManager.Models (Class Library that contains the Domain Model and Data Context Class)
The Domain Model Class is coded as follows:
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace CredentialManager.Models.Entities
{
public class Credential
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long CredentialId { get; set; }
[Required]
public string Username { get; set; }
[Required]
public string Password { get; set; }
[Required]
public string Application { get; set; }
}
}
The Data Context Class is as follows:
using System;
using System.Collections.Generic;
using System.Text;
using CredentialManager.Models.Entities;
using Microsoft.EntityFrameworkCore;
namespace CredentialManager.Models.Context
{
public class CredentialManagerContext : DbContext
{
public CredentialManagerContext(DbContextOptions options)
: base(options)
{ }
public DbSet<Credential> Credentials { get; set; }
}
}
The appsettings.json file looks like the following:
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"ConnectionStrings": {
"i.": null,
"CredentialManagerDB": "server=.\\SQLEXPRESS;database=CredentialManagerDB;Trusted_Connection=true;"
},
"AllowedHosts": "*"
}
The Startup.CS file looks like this:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddDbContext<CredentialManagerContext>(o => o.UseSqlServer(Configuration["ConnectionStrings:CredentialManagerDB"]));
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
}
I then build the Solution and Added Migrations. But when I run update-database, I get the following error:
GenericArguments[0], 'CredentialManager.Models.Migrations.CredentialManagerContext', on 'Microsoft.EntityFrameworkCore.Design.IDesignTimeDbContextFactory`1[TContext]' violates the constraint of type 'TContext'.
Can someone here throw some light on this error ? If I include the classes and data context in the same folder as the API project, then everything works.. But I want these classes to be part of a separate Class Library Project. Any help would be much appreciated.
Thanks.
Update context file to have the following:
public CredentialManagerContext(DbContextOptions<CredentialManagerContext> options)
: base(options)
{ }
As outlined in the documentation:
This requires adding a constructor argument to your DbContext type that accepts :
DbContextOptions<TContext>
This should resolve your issue.
Thank you for all the suggestions. I found a Solution as well. The Startup.cs needs to be informed about the Project that contains the Migrations:
services.AddDbContext<CredManagerContext>(options => options.UseSqlServer(Configuration.GetConnectionString("CredentialManagerDB"), x => x.MigrationsAssembly("CredManager.Models")));
Everything works perfectly after this.

How to migrate a Complex Type to the .net Core Service Implementation

My first time using .net core.
I was able to build a functioning ,net core web application that calls data from my SQL server using Onion Layers. My layout is as below:
Architecture
Core
Application Services
Domain Services
Core.Entity
Infrastructure
UI
API
CemeteryAPI
Web
MVC Web Application
My HomeController has a PageModel with a Complex Type of Search, which consists of about 5 or so ints another 5-6 Lists. In the past I would have done:
var model = new Models.HomePageModel
{
Search = new Business.Search()
};
public partial class Search
{
public String Surname { get; set; }
public String Forename { get; set; }
public String Initials { get; set; }
//etc.
}
I have registered my Services on my startup in ConfigureServices and have attempted to inject this way
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<ICemeteryRepository, CemeteryRepository>();
services.AddScoped<ICountryRepository, CountryRepository>();
//etc
services.AddScoped<ICemeteryService, CemeteryService>();
services.AddScoped<ICountryService, CountryService>();
}
CemeteryService
//ApplicationService
public class CemeteryService : AbstractUnitOfWorkService, ICemeteryService
{
public CemeteryService(IUnitOfWork uow) : base(uow) { }
public int Count()
{
return _unitOfWork.CemeteryRepository.Count();
}
public Cemetery Get(int id)
{
return _unitOfWork.CemeteryRepository.Get(id);
}
public List<Cemetery> List()
{
return _unitOfWork.CemeteryRepository.GetAll().ToList();
}
}
ICemeterRepository
//DomainService
public interface ICemeteryRepository : IRepository<Cemetery>
{
}
CemeteryRepository
public class CemeteryRepository : BaseRepository, ICemeteryRepository
{
public CemeteryRepository(SAWGPDBContext context) : base(context) { }
public int Count()
{
return _context.Cemetery.Count();
}
public Cemetery Get(int id)
{
return _context.Cemetery.Find(id);
}
public IEnumerable<Cemetery> GetAll()
{
return _context.Cemetery;
}
//etc
}
ICemeteryInterface
public interface ICemeteryService
{
int Count();
List<Cemetery> List();
//etc
}
public ActionResult Index([FromServices] ICasualtyService _CasualtyService, IPhotoService _PhotoService, ICountryService _CountryService, ICemeteryService _CemeteryService, IRegimentService _RegimentService)
var model = new Models.HomePageModel
{
Search = new SearchPageModel(_PhotoService, _CasualtyService, _CountryService, _CemeteryService, _RegimentService, )
};
This looked wrong but I couldn't find any proper examples as I wasn't sure what to look for exactly. The above returns
Model bound complex types must not be abstract or value types and must
have a parameterless constructor.
I presume I need to build a SearchService but I'm not entirely clear how to build one for a complex type. Any pointers would be appreciated.

dependency injection into view model class in asp.net core

I am using the following DTO class in one of my api controller class, in an asp.net core application.
public class InviteNewUserDto: IValidatableObject
{
private readonly IClientRepository _clientRepository;
public InviteNewUserDto(IClientRepository clientRepository)
{
_clientRepository = clientRepository;
}
//...code omitted for brevity
}
This is how I using it in a controller
[HttpPost]
public async Task<IActionResult> RegisterUser([FromBody] InviteNewUserDto model)
{
if (!ModelState.IsValid) return BadRequest(ModelState);
//...omitted for brevity
}
But I am getting a System.NullReferenceException in the DTO class
This is happening since dependency injection is not working in the DTO class.
How can I fix this ?
DI will not resolve dependences for ViewModel.
You could try validationContext.GetService in Validate method.
public class InviteNewUserDto: IValidatableObject
{
public string Name { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
IClientRepository repository = (IClientRepository)validationContext.GetService(typeof(IClientRepository));
return null;
}
}
Did you register ClientRepository in startup.cs?
public void ConfigureServices(IServiceCollection services)
{
...
// asp.net DI needs to know what to inject in place of IClientRepository
services.AddScoped<IClientRepository, ClientRepository>();
...
}

Can I use startup.cs to load AppSettings

Can I write code in startup.cs...Configuration method to call my DataAccess layer and/or some other class to assign data to my static class after reading the configurations either from DB or from AppSettings from web.config file to read all my app configurations during the startup. I've tried to access my Static Class in startup.cs by adding reference to the library where my class resided, but I'm not able to access it in my asp.net MVC4 app.
namespace CAS.Common
{
public static class CommonConfiguration
{
public static string CDSRestClient { get; set; }
public static string ClientIdValue { get; set; }
public static string ClientSecretValue { get; set; }
}
}
Code from Startup.cs
using System.Configuration;
using CAS.Common;
namespace myWebApp
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
//This is the intended code, which I'm not able to do as I'm not able to access my static class here.
CommonConfiguration.CDSRestClient = ConfigurationSettings.AppSettings["CDSRestClient"].ToString().Trim();
CommonConfiguration.ClientIdValue = ConfigurationSettings.AppSettings["clientIdValue"].ToString().Trim();
CommonConfiguration.ClientSecretValue = ConfigurationSettings.AppSettings["clientSecretValue"].ToString().Trim();
}
}
}
Can anyone tell me what am I doing wrong here.

NHibernate, AutoMapper and ASP.NET MVC

I'm wondering about a "best practice" using NHibernate, AutoMapper and ASP.NET MVC. Currently, i'm using :
class Entity
{
public int Id { get; set; }
public string Label { get; set; }
}
class Model
{
public int Id { get; set; }
public string Label { get; set; }
}
Entity and model are mapped like this :
Mapper.CreateMap<Entity,Model>();
Mapper.CreateMap<Model,Entity>()
.ConstructUsing( m => m.Id == 0 ? new Entity() : Repository.Get( m.Id ) );
And in the controller :
public ActionResult Update( Model mdl )
{
// IMappingEngine is injected into the controller
var entity = this.mappingEngine.Map<Model,Entity>( mdl );
Repository.Save( entity );
return View(mdl);
}
Is this correct, or can it be improved ?
that's how I was doing in a project:
public interface IBuilder<TEntity, TInput>
{
TInput BuildInput(TEntity entity);
TEntity BuildEntity(TInput input);
TInput RebuildInput(TInput input);
}
implement this interface for each entity or/and for some group of entities you could do a generic one and use it in each controller; use IoC;
you put your mapping code in the first 2 methods (doesn't matter the mapping technology, you could even do it by hand)
and the RebuildInput is for when you get the ModelState.IsValid == false, just call BuildEntity and BuildInput again.
and the usage in the controller:
public ActionResult Create()
{
return View(builder.BuildInput(new TEntity()));
}
[HttpPost]
public ActionResult Create(TInput o)
{
if (!ModelState.IsValid)
return View(builder.RebuildInput(o));
repo.Insert(builder.BuilEntity(o));
return RedirectToAction("index");
}
I actually do sometimes generic controller that is used for more entities
like here: asp.net mvc generic controller
EDIT:
you can see this technique in an asp.net mvc sample application here:
http://prodinner.codeplex.com
I would inject the IMappingEngine into the controller, instead of the using the static Mapper class. You then get all the benefits of being able to mock this in your tests.
Take a look at this link by AutoMapper's creator,
http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/05/11/automapper-and-ioc.aspx