Conditional validation of subclass - c#

I have ASP.NET MVC 3 application with the following class:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Address HomeAddress { get; set; }
// [Optional("MailingAddrressSameAsHome")] - some custom attribute
public Address MailingAddress { get; set; }
public bool MailingAddrressSameAsHome { get; set; }
}
public class Address
{
[Required]
public string Street { get; set; }
...
}
And now I would like to validate, mailing address only when MailingAddressSameAsHome is false. Unfortunatelly I don't known how to stop validating properties in Address class.
Do you have any ideas?

Did you consider only setting MailingAddress when needed, thus letting the property MailingAddrressSameAsHome be read-only:
public bool MailingAddrressSameAsHome
{
//Null means no MailingAddress, which means: use HomeAddress
get { return MailingAddress == null ; }
}
If so, you can validate MailingAddress whenever present.
Regards,
Morten

You could write this with a custom attribute

Related

Deserialization further address of json in c#

I am deserializing a json in c#. but address field needs furher deserialization. help me how to do it
{"Name":"name something",
"Start":"2021-11-10T09:00:00",
"End":"2021-11-14T09:00:00",
"AdditionalInformation":"infoadfasf.",
"Address":{"Information":"Cancha Convive "Parque la Hermandad" colonia El Hogar, Tegucigalpa.","City":"Tegucigalpa, Francisco Moraz\u00e1n","CountryIso2":"HN"}}
i cant get the properties of address, eg address have (city, country..)
my c# code
public class Event
{
public string Name { get; set; }
public DateTime Start { get; set; }
public DateTime End { get; set; }
public string AdditionalInformation { get; set; }
public Address1 address1 { get; set; }
}
public class Address1
{
public string Information { get; set; }
public string City { get; set; }
public string CountryIso2 { get; set; }
}
data service for deserialization
public class DataService
{
public async Task<IEnumerable<Event>?> GetEventsAsync()
{
return JsonSerializer.Deserialize<IEnumerable<Event>>(await File.ReadAllTextAsync("Data/Events.json"));
}
}
The Address field in the JSON is unmatched with the address1 in Event model.
1.1. Either rename the property to Address
public class Event
{
...
public Address1 Address { get; set; }
}
1.2. Or using the JsonProperty attribute:
[JsonProperty("Address")]
public Address1 address1 { get; set; }
Would suggest using the approach 1.1 which is declaring the property with Pascal Casing naming, following the C# naming convention.
The provided JSON is an object, but not an array. You should deserialize as Event but not IEnumerable<Event>. Following change requires to change the method signature for GetEventAsync method as well.
public async Task<Event> GetEventAsync()
{
return JsonSerializer.Deserialize<Event>(await File.ReadAllTextAsync("Data/Events.json"));
}

MVC Entity collections that is sorted

I have the following entity
public class Meeting
{
[Key]
public int Id { get; set; }
public Guid SubjectId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[Required]
public string Email { get; set; }
private ICollection<MeetingPeriod> _meetingTimes;
public virtual ICollection<MeetingPeriod> MeetingTimes
{
get { return _meetingTimes ?? (_meetingTimes = new Collection<MeetingPeriod>()); }
protected set { _meetingTimes = value; }
}
}
Got a few questions:
When I get a record I would like all the MeetingTimes to be sorted by default. Is this possible? I tried to return _meetingTimes.OrderBy but then I could not add any more meeting times as it was a readonly list.
I have added override Equals() to MeetingPeriod object. However when I try to compare MeetingTimes to an array of MeetingPeriod seems like the Equal() isn't getting called. What is going on here? It does get called correctly elsewhere. Seems like something to do with ICollection?

sending Null to a List of Objects in a web service

I have a web service as per the below ;
[Route("/MyService", Verbs = "POST")]
public class MyData
{
public string GUID { get; set; }
public BankDetails BankDetail { get; set; }
public ContactNameData ContactNames { get; set; }
public List<AddressData> Addresses { get; set; }
}
public class AddressData
{
public string address1 { get; set; }
public string address2 { get; set; }
public string address3 { get; set; }
public string postalCode { get; set; }
public string city { get; set; }
public string state { get; set; }
public string countryCode { get; set; }
}
public class ContactNameData
{
public string title { get; set; }
public string firstName { get; set; }
public string middleName { get; set; }
public string lastName { get; set; }
}
public class BankDetails
{
public string sortCode { get; set; }
public string accountNumber { get; set; }
}
public class My_ServiceStack : Service
{
[Authenticate]
public object Post(MyData data)
{
// do something here
}
}
the problem I have is when I need to leave off the List of Addresses. Sending through a null value for the BankDetails object and the ContactNameData object works as expected but sending through a null value for the List gives me a NullExceptionError
How can I fix this so that I can send through a null to the List?
It is difficult to say what is happening without seeing the concrete line where the exception is thrown.
My best guess is that you do something with the list which is not allowed with null. A NullExceptionError does not exist in C# (except you defined such an Error for yourself), so I assume you mean a NullReferenceException. This exception is thrown when you dereference a null object reference. For example, Addresses.Count will throw such an exception because Count can not be used on a non-existing object.
There are several ways to fix such problems; the most common is to check for null before working with the list. Instead of
int addressCount;
addressCount = Addresses.Count;
you would simply write
int addressCount = 0;
if (Addresses != null)
addressCount = Addresses.Count;
For more concrete information, I would have to see what you do with the list that causes the NullReferenceException.
Thanks Nebr. It was a NullReferenceException error that i was getting and was being caused by code within the web service that was doing something with the Address data. Wrapping that code within a != null if statement sorted the issue. It now works as expected
many thanks
Try sending an empty list rather than a null list

Creating new open property

I am trying to do a blog project and I am using ado.net and I have 3-tier architecture.
In one classlibrary I have classes such as User and Comments:
public class User
{
public int userID{ get; set; }
public string userName{ get; set; }
public string userPassword { get; set; }
public string userMail{ get; set; }
}
public class Comments
{
public int ID { get; set; }
public int userID{ get; set; }
public string commentHeader{ get; set; }
public string commentContent{ get; set; }
}
I want to have a userName property in the Comments class. And I decided to create an open property in the Comments class.
Because I will show in these in a UI and I want to see the UserName along with UserID; for a better understanding about whom send this comment.
How I can create the following?
public string userName
{
get
{
return //(what I have to write here)
}
}
Multiple ways to do that.
Assuming you have list of Users in your code, you can query against that list and retrieve the UserName in your property. Something like:
public string userName
{
get
{
return userList.Single(r=>r.UserID == this.UserID).UserName; // Use single
//if you are sure there's going to be a single record against a user ID
//Otherwise you may use First / FirstOrDefault
}
}
Or
you may use composition and place User object inside the Comments class.
public class Comments
{
public int ID { get; set; }
public User user { get; set; } // User object in Comments class
public string commentHeader{ get; set; }
public string commentContent{ get; set; }
}
and then in your property you can simply do:
public string userName
{
get
{
return user.UserName;
}
}
public string userName
{
get
{
return userList.FirstOrDefault(user => user.userID == userID).userName;
}
}
where userList is
List<User> userList;

Accessing Class and Property name inside an Attribute

Is there any way to access the Class and Property name which you attached an attribute to inside the attribute?
For example
public class User {
public string Email { get; set; }
public string FirstName { get; set; }
[MyAttribute]
public string LastName { get; set; }
}
And then in the MyAttribute class
public class MyAttributeAttribute {
public MyAttributeAttribute () : base() {
string className = /*GET CLASS NAME - should return "User" */
string propertyName = /*GET PROPERTY NAME - should return LastName*/
}
}
I know I can pass in the information in the constructor, but hoping there is an easy way somehow to save on retyping info over and over again either via reflection or...
Sorry, but no that's not possible. You could also have
public class User {
public string Email { get; set; }
public string FirstName { get; set; }
[MyAttrubute]
public string LastName { get; set; }
}
[MyAttrubute]
public class OtherClass {
[MyAttrubute]
public string AnotherProperty { get; set; }
}
The attribute can be created from anywhere. Even the following is a valid way to create an instance:
var att = new MyAttribute();
Your question could be boiled down to "Can I detect where my custom class is instantiated from?". In my last example, StackTrace could probably be used. But with attributes they are being constructed by the .NET runtime, so you would not be able to go that route.

Categories