Generics where <t> Class library and MVC app - c#

I'm trying to learn how to use the 'where' in Generic, I seem to have it working but I not sure if how I have done it is the correct way.
Currently I have in a class library:
public class NewMembersViewModel
{
public NewMembersViewModel()
{
Id = Guid.NewGuid().ToString();
}
[Display(Name = "Username")]
[RemoteUsernameValidation("IsUserNameTaken", "Register", ErrorMessage = "Username already taken")]
public string MemberUsername { get; set; }
[Display(Name = "Password")]
public string MemberPassword { get; set; }
[Display(Name = "Email")]
[RemoteEmailValidation("IsEmailTaken", "Register", ErrorMessage = "Email already in use")]
public string MemberEmail { get; set; }
[Display(Name = "Mobile Number")]
[RemoteMobileValidation("IsMobileTaken", "Register", ErrorMessage = "Mobile Number already in use")]
public string MemberMobile { get; set; }
[Display(Name = "Forename")]
public string MemberForename { get; set; }
[Display(Name = "Surname")]
public string MemberSurname { get; set; }
public string Id { get; set; }
public int VerificationCode { get; set; }
}
And
public static class SqlDatabaseMethods<T> where T : NewMembersViewModel
{
public static bool LoginUser(T member)
{
var p = member.MemberEmail;
return true;
}
public static bool AddNewMember(T member)
{
var name = member.MemberForename;
return true;
}
}
Then in my MVC app I have:
bool name = SqlDatabaseMethods<NewMembersViewModel>.AddNewMember(model);
if (name)
{
var test = "works";
}
This does work, can anyone tell me whether I doing it correctly, as all examples I have seen appear to be console apps

Generics make sense when you need have some functionality which is common across multiple classes. In this case where clause defines what the constraints of your generic type are. In such case generic methods help to re-use functionality.
In your case it doesn't seem that SqlDatabaseMethods<T> could be re-used more than once, as model NewMembersViewModel seems to be very specific and hardly re-usable elsewhere.
In your code you are using generics correctly, but in my opinion you don't need generics here at all. You could just as easily use the following code without the overhead of generics:
public static class SqlDatabaseMethods
{
public static bool LoginUser(NewMembersViewModel member)
{
var p = member.MemberEmail;
return true;
}
public static bool AddNewMember(NewMembersViewModel member)
{
var name = member.MemberForename;
return true;
}
}
And then call the method like this:
bool name = SqlDatabaseMethods.AddNewMember(model);
if (name)
{
var test = "works";
}

Related

Blazor trigger custom validation message

I have the following class which is being used as an input model for an EditForm in a Blazor server side application.
public class KundeInput
{
[ValidateComplexType]
public List<AnsprechpartnerInput> Ansprechpartner { get; } = new List<AnsprechpartnerInput>();
public string? Kundennummer { get; }
[Required]
[MaxLength(60)]
public string Firma { get; set; } = String.Empty;
[MaxLength(60)]
public string? Name2 { get; set; }
[MaxLength(60)]
public string? Name3 { get; set; }
}
As you can see, my model contains a list of another model called AnsprechpartnerInput. Here is this model:
public class AnsprechpartnerInput
{
public string? Kundennummer { get; set; }
public int Nummer { get; } = -1;
[MaxLength(60)]
[Required]
public string Vorname { get; set; } = String.Empty;
[MaxLength(60)]
[Required]
public string Nachname { get; set; } = String.Empty;
[MaxLength(40)]
[Required]
public string? Bereich { get; set; }
/ * More properties */
}
The validation works fine. However, once I have multiple invalid AnsprechpartnerInput models in my list, the ValidationSummary becomes a mess. Because it displays e.g. 5 times field xyz is invalid.
I know I can set a custom message with the ErrorMessage property but I am not able to use other attributes from my model in this message.
What I want to achive is this:
[Required(ErrorMessage = $"Vorname of {Kundennummer} is required")]
public string Vorname { get; set; } = String.Empty;
I already tried to change the message with reflection but accoridng to Microsoft this way is not recommend or supported
https://github.com/dotnet/aspnetcore/issues/25611
Is there any way to get it to work? I thought of string replacement but I am not sure how I can figure out the right model for my ValidationMessage.
Also is there any way to validate the items of the list by one and get a boolean result? Let's say I want to achive this:
#foreach (var ansprechpartner in Input.Ansprechpartner)
{
if (Input.SelectedAnsprechpartner is null)
Input.SelectedAnsprechpartner = ansprechpartner;
<a #onclick="() => Input.SelectedAnsprechpartner = ansprechpartner"
class="#GetNavListClass(Input.SelectedAnsprechpartner == ansprechpartner)"
id="list-ansprechpartner-tab-#(ansprechpartner.Nummer)"
data-toggle="list"
href="#list-ansprechpartner-#(ansprechpartner.Nummer)"
role="tab"
aria-controls="#(ansprechpartner.Nummer)">
#((MarkupString)(ansprechpartner.Nummer < 0 ? "<span class=\"font-weight-bold\">NEU</span>" : $"({ansprechpartner.Nummer})")) #ansprechpartner.Vorname #ansprechpartner.Nachname
</a>
// When the model ansprechpartner is invalid, I want to display an icon
}
Thanks for any help!
PS: Blazor rocks!
You should use a custom validation attribute where you can explicitly add any error message you want
public class KundennummerValidationAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var model = (AnsprechpartnerInput)validationContext.ObjectInstance;
if(string.IsNullOrEmpty((string)value))
{
return new ValidationResult($"Vorname of {model.Kundennummer} is required", new[] { "Kundennummer" });
}
return ValidationResult.Success;
}
}
then use
[KundennummerValidation]
public string Vorname { get; set; } = String.Empty;
result :
Validation summary:

Best pattern to validate DataContract properties conditionally

I have data class using DataContract and implementing field validation using System.ComponentModel.DataAnnotations.
In my class, the type attribute renders some fields relevant while others are not applicable. That is, some fields, depending on the type attribute, will become invalid while others are valid.
I am trying to find a good pattern to validate such conditions in an elegant fashion. I am open to accepting that running into this situation might mean I need to break my class in a few chunks to accommodate such polymorphism. Although not sure how.
Just in case it is relevant, those data classes will be serialized and stored on ServiceFabric reliable collections. This validation if more from an API perspective.
As of today, I am performing the validation in this way (which I do not find satisfactory) in the endpoint controller.
if (voucher.ServiceType == ServiceType.VaccineCompany)
{
if (voucher.Asignee == null)
{
throw new ArgumentNullException("Asignee is required for company vaccine voucher");
}
if (!voucher.BookingTime.HasValue)
{
throw new ArgumentNullException("Booking time is required for company vaccine voucher");
}
if (!voucher.FixedPrice.HasValue)
{
throw new ArgumentNullException("Fixed price is required for company vaccine voucher");
}
if (voucher.Discount.HasValue)
{
throw new ArgumentNullException("Discount is not a valid argument for company vaccine type voucher");
}
}
if (voucher.ServiceType == ServiceType.Vaccine)
{
if (voucher.Asignee != null)
{
throw new ArgumentException("Invalid argument asignee");
}
if (voucher.BookingTime.HasValue)
{
throw new ArgumentNullException("Invalid argument booking time");
}
if (voucher.FixedPrice.HasValue && voucher.Discount.HasValue)
{
throw new ArgumentException("Fixed price and discount cannot be set simultaneously");
}
}
This is how the model looks like:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
namespace Remoting.VoucherService
{
[DataContract]
public sealed class Voucher
{
[Required(ErrorMessage = "Code is required")]
[DataMember(Name = "code")]
public string Code { get; set; }
[Required(ErrorMessage = "Description is required")]
[DataMember(Name = "description")]
public string Description { get; set; }
[Required(ErrorMessage = "ServiceType is required")]
[DataMember(Name = "serviceType")]
public ServiceType ServiceType { get; set; }
[DataMember(Name = "discount")]
public double? Discount { get; set; }
[DataMember(Name = "fixedPrice")]
public double? FixedPrice { get; set; }
[DataMember(Name = "isValid")]
public bool Valid {
get { return TimesUsed < MaxUsage; }
set { }
}
[DataMember(Name = "maxUsage")]
public uint MaxUsage { get; set; } = 1;
[DataMember(Name = "asignee")]
public string Asignee;
[DataMember(Name = "bookingTime")]
public DateTime? BookingTime;
[DataMember(Name = "timesUsed")]
public uint TimesUsed { get; set; } = 0;
public void IncreaseUsage()
{
TimesUsed += 1;
}
private ExtensionDataObject data;
public ExtensionDataObject ExtensionData
{
get => data;
set => data = value;
}
}
}
I hope somebody can provide me with some insights!

Compare Multiple Variables to Same Value Efficiently

I'm looking for alternative methods in C# to compare multiple variables to the same value, and I would optimally like for them to share the same subsequent instructions based on their conditional results.
For example, I have the following code:
string DOBResultsError = VerifySingleRecordReturned(DOBResults, APIParameters, 1);
string NameResultsError = VerifySingleRecordReturned(NameResults, APIParameters, 2);
if (DOBResultsError != string.Empty)
{
PatientRecordUpdate(DOBResults, APIParameters.PatientID, DOBResultsError);
}
else if (NameResultsError != string.Empty)
{
PatientRecordUpdate(NameResults, APIParameters.PatientID, NameResultsError);
}
I'm having to do explicitly instruct PatientRecordUpdate to be performed for each variable being compared to String.Null.
What I would like to have happen is something like the following:
if (DOBResultsError != string.Empty || NameResultsError != string.Empty)
{
//whichever isn't an empty string use to perform PatientRecordUpdate()
}
Is such syntax possible in C#?
Employing the switch keyword won't make a difference because even though I can have multiple circumstances resulting in the same instructions being performed, if I need to use the one of the comparison variables I would still need to explicitly state the code using the variable for each possible case.
string DOBResultsError = VerifySingleRecordReturned(DOBResults, APIParameters, 1);
string NameResultsError = VerifySingleRecordReturned(NameResults, APIParameters, 2);
string SSNResultsError = VerifySingleRecordReturned(SSNResults, APIParameters, 3);
string EmptyString = String.Empty;
switch (EmptyString)
{
case DOBResultsError:
case SSNResultsError: //can't use SSNResultsError with PatientRecordUpdate() without stating PatientRecordUpdate() again
PatientRecordUpdate(DOBResults, APIParameters.PatientID, DOBResultsError);
case NameResultsError:
PatientRecordUpdate(NameResults, APIParameters.PatientID, NameResultsError);
}
Any help appreciated.
UPDATE: Requested additional info
This is what VerifySingleRecordReturnedFrom() does. It checks a few conditions that would cause errors in the program and writes an error message to be added on the record in an SQL DB.
public static string VerifySingleRecordReturnedFrom(List<PatientList3> ReturnedPatientList, AutoPatientLookup APIParameters, int SearchCriteria = 0)
{
string ErrorMessage = String.Empty;
if (ReturnedPatientList.Count == 0)
{
//Error Message for Dob
if (SearchCriteria == 1)
{
ErrorMessage = string.Format("No patients were returned from for DOB ....");
return ErrorMessage;
}
//Error Message for Name
else if (SearchCriteria == 2)
{
ErrorMessage = string.Format("No patients were returned from for patient name ....");
return ErrorMessage;
}
//Error Message for PracticePatientNumber
else if (SearchCriteria == 3)
{
ErrorMessage = string.Format("No patients were returned from for PracticePatientNumber...");
return ErrorMessage;
}
}
// more than one patient in common results list from AttemptToMatchPatientsByDemographics() or results using PatientNumber
else if (ReturnedPatientList.Count() > 1)
{
switch(SearchCriteria)
{
case 1:
case 2:
ErrorMessage = String.Format("{0} number of patients were returned...");
break;
//More than one patient returned from for any given PracticePatientNumber
case 3:
ErrorMessage = String.Format("{0} number of patients were returned....");
break;
}
return ErrorMessage;
}
//No error in number of results from
return ErrorMessage;
}
All of the results(DOB/Name/SSN) types are List objects of the following PatientList3 object (I've included sub classes):
public class PatientList3
{
public Patient PatientNameID { get; set; }
public string PatientNumber { get; set; }
public string ChartNumber { get; set; }
public Gender2 Gender { get; set; }
public string DOB { get; set; }
public string PhoneNumber { get; set; }
public string SSN { get; set; }
}
public class Patient
{
public int ID { get; set; }
public PtName Name { get; set; }
}
public class PtName
{
public string First { get; set; }
public string Middle { get; set; }
public string Last { get; set; }
public string Suffix { get; set; }
public string Full { get; set; }
public string Preferred { get; set; }
}
public class Gender2
{
public string LookupType { get; set; }
public string Code { get; set; }
public string Description { get; set; }
public int Order { get; set; }
public bool Active { get; set; }
public List<AlternateCodes> AlternateCodes { get; set; } //Not important, didn't include AlternativeCodes class
}
This is the class of APIParameters:
public class AutoPatientLookup
{
public string DOB { get; set; }
public string Gender { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int? PatientNumber { get; set; }
public string SSN { get; set; }
public int PracticeID { get; set; }
public int PatientID { get; set; }
}
Consider leveraging a base result type for some generic logic like this:
// assuming both results inherit from or implement some base type...
List<ResultBase> results = new List<ResultBase>()
{
DOBResults,
NameResults
}; // order matters since it's used for the parameter index
// Note that a class would be a much better option than a tuple here.
// Select will verify each result but only upon request until FirstOrDefault is fulfilled
Tuple<ResultBase, string> firstResultError = results
.Select((result, index) => new Tuple<ResultBase, string>(
result,
VerifySingleRecordReturned(result, APIParameters, index + 1)))
.FirstOrDefault(result => !string.IsNullOrEmpty(result.Item2 /* Error message */));
// If there was at least one error, call the original patient update record
// with the associated information.
if (firstResultError != null)
{
PatientRecordUpdate(
firstResultError.Item1 /* Failed result */,
APIParameters.PatientID,
firstResultError.Item2 /* Error message for that result */);
}
You'll want to use a new class instead of a tuple for maintainability reasons, but besides that this should get you started in a good direction.

MVC - using enum in the DisplayAttribute of a Model class

My questions is: I have an enum class as:
public enum EnumApplications
{
Android = 1,
IOS = 2
}
Also I have a Model which is for Creating a new user. a user can be defined as Active in any of these application when we create a new user.
My model is:
public class NewUserModel
{
public int UserId { get; set; }
[Required]
[Display(Name = "FirstName")]
public string FirstName { get; set; }
[Required]
[Display(Name = "LastName")]
public string LastName { get; set; }
public int ClientId { get; set; }
[Required]
[Display(Name = "Email")]
[EmailAddress]
public string EmailAddress { get; set; }
[Display(Name = "Is Active in IOS")]
public bool IsActiveInApp1 { get; set; }
[Display(Name = "Is Active in Android")]
public bool IsActiveInApp2 { get; set; }
}
What I want to do is in the: [Display(Name = "Is Active in Android")]
I want to use the enum so if the app name gets changed I don't need to change it here, something like:
EnumApplications.IOS.ToString()
Here's a screenshot for better understanding:
"I want to use the enum so if the app name gets changed I don't need to change it here"
No, there is no easy way to do this.
the only implementation I can think of (aside from runtime assembly/type compiling and generation) that you could do that, is a T4 template. the template would generate the model, and you would have to run it after modifying your enum.
in regards to your question title and comment:
MVC - Using Enum In The DisplayAttribute of a Model class
what I want is in my model instead of saying [Display(Name = "Is Active in IOS")] and hardcoding IOS. I want to get the name of IOS from my enum.
The following solution (which isn't T4 or Runtime compiling) just inherits DisplayNameAttribute and uses the constructor of your type to pass the parameter to the base type.
It is a solution in the sense that if you were to change Android to Andy you would use a refactor tool ( built-in intellisense tool these days) to implement that change across code files that references that value type.
public enum MyEnum
{
NotSet = 0,
iOS = 1,
Android = 2
}
class MyDisplayNameAttribute : System.ComponentModel.DisplayNameAttribute
{
public MyDisplayNameAttribute(MyEnum myEnum)
: base("Is Active in " + myEnum.ToString())
{
}
public override string DisplayName
{
get
{
// you could do the "Is Active in " here, but I doubt control frameworks would use it.
return base.DisplayName;
}
}
}
public class MyModel
{
[MyDisplayName(MyEnum.iOS)]
bool IsActiveApp1 { get; set; }
// uses standard 'DisplayNameAttribute' type for test below
[System.ComponentModel.DisplayName("Is Active in Android")]
bool IsActiveApp2 { get; set; }
}
For quick testing, we'll do what control frameworks do, reflect over the provided type and get the CustomAttribute.. note that there is more type checking involved, we'll casting it to DisplayNameAttribute for brevity.
string[] PropertyNames = new string[] { "IsActiveApp1", "IsActiveApp2" };
System.Type MyModelInfo = typeof(MyModel);
PropertyNames.SelectMany(prop => MyModelInfo.GetProperty(prop).GetCustomAttributes(true))
.ToList().ForEach((attr) =>
{
Console.WriteLine(((System.ComponentModel.DisplayNameAttribute)attr).DisplayName);
});

C# access T of generic class in its own method

Im just starting with generics and was wondering how I can access T of the class in a class method? Lets take some code to explain better what I want to do:
public class RegisterResult<T> where T : IRegisterable
{
public bool Success { get; set; }
public string Entity { get; set; }
public string ErrorMessage { get; set; }
//Want to avoid this, by using generics:
/*public static RegisterResult UserSuccess = new RegisterResult(true, "User", "");
public static RegisterResult DeviceSuccess = new RegisterResult(true, "Device", "");
public static RegisterResult DeviceDataSucces = new RegisterResult(true, "DeviceData", "");*/
public RegisterResult(bool success, string errmsg)
{
this.Success = success;
//The following line does not work, so how can I reach that?
this.Entity = T.GetType().Name;
this.ErrorMessage = errmsg;
}
}
Thank you very much for all helpful and well meant answers!
UPDATE: Errormessage from Visual Studio
"T" is "type Parameter" and not valid in given context
Simple as this:
this.Entity = typeof(T).Name;

Categories

Resources