Create blazor component based on InputBase with interface - blazor-server-side

I need to create a Blazor component inherited from the Microsoft.AspNetCore.Components.Forms.InputBase class that implements an interface.
My interface is realised with this code :
public interface Person
{
public Guid Id { get; set; }
public string Name { get; set; }
public string FirstName { get; set; }
}
And my class who inherit of interface is
public class Child : Person
{
private Guid id;
private string name;
private string firstName;
public Guid Id { get => id; set => id = value; }
public string Name { get => name ; set => name = value; }
public string FirstName { get => firstName; set => firstName = value; }
public Child(string name, string firstname)
{
this.name = name;
this.firstName = firstname;
}
}
For my component this inherit of InputBase is declared with :
#inherits Microsoft.AspNetCore.Components.Forms.InputBase<Person?>
For use my component in blazor page, I have used the code below :
<MyTest #bind-Value="#child" />
When I generate my solution, I have an error :
Error CS1503 Argument 2: cannot convert from 'Microsoft.AspNetCore.Components.EventCallback<Test.Children>' to 'Microsoft.AspNetCore.Components.EventCallback'
Can you help me understand this mistake? Do I need to create a specific getter/setter to transform the Child into a Person or is there another solution?
Thanks for your help !
Vincent

Related

Get actual model type from dynamic type

I have three tables in my database (Student, Course, All). When I add any data in Student & Course table, the data also gets added in All table.
So, I'm using dynamic type data to pass Student & Course type data to get saved in All table.
public IActionResult Add(Student model)
{ ...
bool studentData = _studentService.Add(model); //saving in Student table
bool allData= _allService.AddAll(model); // passing 'Student' type data
...
}
In the All service, I've a function like-
public bool AddAll(dynamic model) // 'Student' type data passed & received as dynamic
{...}
Now, I need the details about Student model type (table name, total data found etc.).
Is there any way to get it? And is it possible to get the Student or Course model type info if I use dynamic data type?
Any suggestion or help will be much appreciated :) Thanks in advance!
If you want to get model type,you can use model.GetType(),and you can use model.GetType().Name to get model type Name,here is a demo:
Model:
public class Student
{
public int StudentId { get; set; }
public string StudentName { get; set; }
}
public class Course
{
public int CourseId { get; set; }
public string CourseName { get; set; }
}
Action:
public void Add(Student model)
{
//Student s = new Student { StudentId=1, StudentName="s1" };
Course c = new Course { CourseId=1,CourseName="c1" };
bool allData = AddAll(c);
}
public bool AddAll(dynamic model)
{
var type = model.GetType();
var typeName = type.Name;
return true;
}
result:
Is this example demonstrate what you trying to do ?
// Some dummy classes
public class Student
{
public string Name { get; set; }
public Student(string name)
{
Name = name;
}
}
public class Course
{
public string Title { get; set; }
public Course(string title)
{
Title = title;
}
}
// put the method somewhere
private string TypeCasting(dynamic myContent)
{
if (myContent is Student littleStudent)
{
return littleStudent.Name;
}
if (myContent is Course someLovelyCourse)
{
return someLovelyCourse.Title;
}
return string.Empty;
}
// Example using
var student = TypeCasting(new Student("fossil"));
var course = TypeCasting(new Course("type casting"));

Automapper multiple source to single target in v8.0

I'm new to the whole Automapper world in .net core 3.1 and was going through the docs and SO, but couldnt' find anything for my use case from their latest version 8.0.
Borrowing from another SO post, how could I do this in the new v8.0 configuration?
public class People {
public string FirstName {get;set;}
public string LastName {get;set;}
}
public class Phone {
public string Number {get;set;}
}
Convert to a PeoplePhoneDto like this:
public class PeoplePhoneDto {
public string FirstName {get;set;}
public string LastName {get;set;}
public string PhoneNumber {get;set;}
}
Would I use still do this?
Mapper.CreateMap<People, PeoplePhoneDto>();
Mapper.CreateMap<Phone, PeoplePhoneDto>()
.ForMember(d => d.PhoneNumber, a => a.MapFrom(s => s.Number));
Here is a working demo like below:
Model:
public class People
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Phone
{
public string Number { get; set; }
}
public class PeoplePhoneDto
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string PhoneNumber { get; set; }
}
AutoMapper profile:
public class AutoMapperProfile : Profile
{
public AutoMapperProfile()
{
CreateMap<People, PeoplePhoneDto>();
CreateMap<Phone, PeoplePhoneDto>()
.ForMember(d => d.PhoneNumber, a => a.MapFrom(s => s.Number));
}
}
Startup.cs:
services.AddAutoMapper(typeof(AutoMapperProfile));
Controller:
public class HomeController : Controller
{
private readonly IMapper _mapper;
public HomeController(IMapper mapper)
{
_mapper = mapper;
}
public IActionResult Index()
{
var people = new People() { FirstName = "aaa", LastName = "bbb" };
var phone = new Phone() { Number = "12345" };
var model = _mapper.Map<PeoplePhoneDto>(people); // map dto1 properties
_mapper.Map(phone, model);
//do your stuff...
return View();
}
}
Result:

Multiple partial validations

The system I'm developing uses FluentValidation (v5.0.0.1).
What I want to do is create several validators that partially validate an object, which I can then combine in other validators depending on what is required at the time.
For example, say my class has name and address. (This can't be split into a separate class like in the examples).
For scenario 1, I want to validate the name only, so I write a name validator class.
For scenario 2, I only want to validate the address, so I write an address validator class.
For scenario 3, I want to validate both the name and the address, so I want to write a new validator class that calls the name validator and then the address validator.
I don't want to repeat the code in different places, which is why I want them separate. I also don't want to use the When operator as there is no way to determine the when from the contents of the object.
I know I can call SetValidator, but how do I write the call?
RuleFor(j=>j).SetValidator(new NameValidator());
RuleFor(j=>j).SetValidator(new AddressValidator());
doesn't work.
I will explain the solution with this example. I'm going to validate this Contact entity:
public class Contact
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string PostalCode { get; set; }
}
The requirement is validate FirstName and LastName then Address1, Address2, City, PostalCode and have the posibility to reuse our validators in other entities.
Create interfaces to define what an specific entity is.
public interface IAmPerson
{
string FirstName { get; set; }
string LastName { get; set; }
}
public interface IHaveAddress
{
string Address1 { get; set; }
string Address2 { get; set; }
string City { get; set; }
string PostalCode { get; set; }
}
Now Contact entity has to implement both interfaces:
public class Contact : IAmPerson, IHaveAddress
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string PostalCode { get; set; }
}
Then, create the first validator for an IAmPerson entity
public class PersonValidator : AbstractValidator<IAmPerson>
{
public PersonValidator()
{
RuleFor(data => data.FirstName).Length(3, 50).WithMessage("Invalid firstName");
RuleFor(data => data.LastName).Length(3, 50).WithMessage("Invalid LastName");
}
}
The second one for IHaveAddress entity
public class AddressValidator : AbstractValidator<IHaveAddress>
{
public AddressValidator()
{
RuleFor(data => data.Address1).NotNull().NotEmpty().WithMessage("Invalid address1");
RuleFor(data => data.Address2).NotNull().NotEmpty().WithMessage("Invalid address2");
RuleFor(data => data.City).NotNull().NotEmpty().WithMessage("Invalid City");
RuleFor(data => data.PostalCode).NotNull().NotEmpty().WithMessage("Invalid PostalCode");
}
}
Way to use your custom validators
public class ContactValidator: AbstractValidator<Contact>
{
public ContactValidator()
{
RuleFor(contact => contact).SetValidator(new PersonValidator());
RuleFor(contact => contact).SetValidator(new AddressValidator());
}
}
Now you can use your validators to validate person data or address data in any other entity. The unique thing you have to do is implement specific interfaces in the entities you are going to validate.
[UPDATE]
You can increase readability of your code by adding extension methods
public static class ValidatorExtensions
{
public static IRuleBuilderOptions<T, IHaveAddress> MustHaveAValidAddress<T>(this IRuleBuilder<T, IHaveAddress> ruleBuilder)
{
return ruleBuilder.SetValidator(new AddressValidator());
}
public static IRuleBuilderOptions<T, IAmPerson> MustBeAValidPerson<T>(this IRuleBuilder<T, IAmPerson> ruleBuilder)
{
return ruleBuilder.SetValidator(new PersonValidator());
}
}
This is the final result using the extension methods I have just added:
RuleFor(contact => contact).MustBeAValidPerson();
RuleFor(contact => contact).MustHaveAValidAddress();
If you set a validator on the same type as you have, it will only use the last validator set on the type (in your case the AddressValidator). You can create some methods to encapsulate the validation and use Must.
Note that you won't be able to re-use the same error code or error message across these different validations.
public static class Validations
{
public static bool ValidateName(string name)
{
return name != null; //Or any other validation
}
public static bool ValidateAddress(string address)
{
return !string.IsNullOrEmpty(address); //Or any other validation
}
}
Scenario 1
RuleFor(j=>j.Name).Must(Validations.ValidateName);
Scenario 2
RuleFor(j=>j.Address).Must(Validations.ValidateAddress);
Scenario 3
RuleFor(j=>j.Name).Must(Validations.ValidateName);
RuleFor(j=>j.Address).Must(Validations.ValidateAddress);

Conditional Restrictions in Fluent NHibernate using Query Object Pattern

I'm a complete noob to Fluent NHibernate, and I'm using the Query Object Pattern based on a recommendation. Which I'm also new to. I'll try to keep the code samples concise and helpful.
User class:
public class User {
public Guid ID { get; set; }
public string Name { get; set; }
}
Visibility:
public enum VisibilityType {
Anybody,
OwnersOnly,
Nobody
}
Car class:
public class Car {
public Guid ID { get; set; }
public VisibilityType Visibility { get; set; }
public ICollection<User> Owners { get; set; }
}
So I need to write a conditional restriction method for the query object. Return all cars that have VisibilityType.Public, but if a car has Visibility property value of VisibilityType.OwnersOnly, restrict the return to users who belong to that group.
Here's the current restriction method that I have working, but without the condition:
public class CarQueryObject
{
private User user { get; set; }
private const string OwnersProperty = "Owners";
private const string OwnersIDProperty = "Owners.ID";
public CarQueryObject RestrictToOwners()
{
// How do I add a conditional criteria here? Only restrict by owner
// if the QueryObject has VisibilityType.OwnersOnly? Note that it should
// *NOT* restrict VisibilityType.Anybody
CreateOwnersAlias();
Criteria.Add(Restrictions.Eq(OwnersIDProperty, user.Id));
return this;
}
public CarQueryObject JoinFetchOwned()
{
Criteria.SetFetchMode(OwnersProperty, FetchMode.Join);
return this;
}
public void CreateOwnersAlias()
{
Criteria.CreateAlias(OwnersProperty, OwnersProperty, JoinType.LeftOuterJoin);
JoinFetchOwned();
}
}
?_?
an idea to get shown cars
var carsShown = session.CreateCriteria<Car>()
.JoinAlias("Owner", "owner")
.Add(Expressions.Or(
Expression.Eq("Visibility", Visibility.Anybody),
Expression.Eq("Visibility", Visibility.OwnersOnly) && Expression.Eq("owner.Id", currentUser.Id)
))
.List<Car>();

Using fluent-nhibernate is it possible to automap a Value Object(s) inside an Entity?

I'm using Sharp Architecture and have a number of situations where Value Objects are used in an Entity. Here is an obvious simple example:
public class Person : Entity
{
protected Person(){}
public Person(string personName)
{
this.PersonName = personName;
}
public virtual string PersonName { get; protected set;}
public virtual StreetAddress MailingAddress { get; set; }
}
public class StreetAddress : ValueObject
{
protected StreetAddress(){}
public StreetAddress(string address1, string address2, string city, string state, string postalCode, string country )
{
this.Address1 = address1;
this.Address2 = address2;
this.City = city;
this.State = state;
this.PostalCode = postalCode;
this.Country = country;
}
public virtual string Address1 { get; protected set; }
public virtual string Address2 { get; protected set; }
public virtual string City { get; protected set; }
public virtual string State { get; protected set; }
public virtual string PostalCode { get; protected set; }
public virtual string Country { get; protected set; }
}
This of course throws: An association from the table Person refers to an unmapped class: Project.Domain.StreetAddress
because the the AutoPersistenceModelGenerator only includes classes with type IEntityWithTypedId<>. Its not clear how Sharp Architecture expects this common condition to be implemented. Does this have to be handled with a bazillion overrides?
You could change the GetSetup() method in AutoPersistenceModelGenerator to something like:
private Action<AutoMappingExpressions> GetSetup()
{
return c =>
{
c.IsComponentType = type => type.BaseType == typeof (ValueObject);
};
}
I'll try to get the blogpost I saw covering this posted for credit.
You would want to map this as a component. You can use the mapping overrides in Fluent NHibernate to accomplish this.
I agree with Alec. I would map this as a component.
For more information on that, see this SO question:
AutoMapping a Composite Element in Fluent Nhibernate
There, you'll also find info on how to map a collection of composite elements.