Return Empty String Instead of Null - c#

I am using ef core and mapster. I have some columns in my db that are nullable.
When I get them from the db, C# stores them as nulls(which makes sense). I want to return these fields are empty strings though when I send them back via my api.
public class CompanyDto
{
public string Website { get; set; }
}
public class Company
{
public int Id { get; set; }
public string Website { get; set; } = "";
}
company.Adapt<CompanyDto>()
what is the best way to make it so Website in the CompanyDto is an empty string.

Classic setter will do the job as well
public class Company
{
public int Id { get; set; }
private string _website;
public string Website
{
get { return _website; }
set { _website = value ?? string.Empty; }
};
public Company ()
{
_website = string.empty;
}
}

Related

Update entire object in c# .net EF with HttpPut without having to specify all variables

I'm working on a API and I want to update an object. It's working fine right now, but I haven't included all data yet. The list of foundPerson.somevalue = person.somevalue will be very long with all this data. Is there a shorter way of updating the object? It would be nice if I could just update the entire object instead of having to specify all values. I tried foundpersond = person but that does not work.
My code:
public Person UpdatePerson(Person person)
{
var foundPerson = _appDbContext.Persons.FirstOrDefault(result => result.name == person.name);
if(foundPerson != null)
{
foundPerson.value1.anothervalue1 = person.value1.anothervalue1;
foundPerson.value1.anothervalue2 = person.value1.anothervalue2;
foundPerson.value2.anothervalue1 = person.value2.anothervalue1;
foundPerson.value2.anothervalue2 = person.value2.anothervalue2;
foundPerson.value2.anothervalue3 = person.value2.anothervalue3;
_appDbContext.SaveChanges();
return foundPerson;
}
return null;
}
Edit: This is how my Person class and the value classes look like.
public class Person
{
public Value1 Value1 { get; set; }
public Value2 Value2 { get; set; }
}
public class Value1
{
public string Anothervalue1 { get; set; }
public string Anothervalue2 { get; set; }
}
public class Value2
{
public string Anothervalue1 { get; set; }
public string Anothervalue2 { get; set; }
public string Anothervalue3 { get; set; }
}
_appDbContext.Entry(foundPerson).CurrentValues.SetValues(person);
I think it won't work well on Value1 and Value 2 so you might need to use the same approach on them

Invoking a method from constructor

I am invoking a method in my constructor like below.Is this the right way to do to set properties based on some validations.Please suggest.
public class Asset
{
public Asset(string id)
{
SetStorageId(id);
}
public string AssetId { get; set; }
public string UtilId { get; set; }
public string MappingId { get; set; }
public bool IsActive { get; set; }
private void SetStorageId(string id)
{
if (Regex.Match(id, "^[A-Z][a-zA-Z]*$").Success)
{
AssetId = id;
}
else
{
UtilId = id;
}
}
}
In my opinion your design should be like below,
You should abstract common items to base class and create specific class inheriting this,
and decide from client(consumer) which instance do you need and construct it
public class AssetBase
{
public string MappingId { get; set; }
public bool IsActive { get; set; }
}
public class Asset : AssetBase
{
public string AssetId { get; set; }
}
public class Util : AssetBase
{
public string UtilId { get; set; }
}
static void Main(string[] args)
{
string id = Console.ReadLine();
if (Regex.Match(id, "^[A-Z][a-zA-Z]*$").Success)
{
Asset asset = new Asset();
asset.AssetId = id;
}
else
{
Util util = new Util();
util.UtilId = id;
}
}
simply try this
public class Asset
{
private string id;
public string AssetId { get; set; }
public string UtilId { get; set; }
public string Id
{
set
{
if (Regex.Match(value, "^[A-Z][a-zA-Z]*$").Success)
{
this.id = value;
}
else
{
UtilId = value;
}
}
get
{
return id;
}
}
}
When you create a property in c#, a private variable is created for that property on compile time. When you try to set the Id property in the code above the Id you pass goes into the value keyword and you can perform your validations on the value keyword and set your property accordingly.
No need to complicate your code with set methods, constructors or deriving classes
or you can even use data annotations which is a more elegant way https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validationattribute.aspx#Properties
using System.ComponentModel.DataAnnotations;
public class Asset
{
[RegularExpression("^[A-Z][a-zA-Z]*$")]
public string Id { get; set; }
}
It's not wrong. It can possibly grow to be a little confusing. Maybe you can make it clearer by moving the bod of SetStorageId to the constructor. Perhaps there is no need to complicate with subclassing, relative to other code within the project.

parse nested json string in c#

i have json string as
{"AccountNo":"345234533466","AuthValue":"{\"TopUpMobileNumber\":\"345234533466\",\"VoucherAmount\":\"100\"}"}
to parse this string i have created class as
public class UserContext
{
public string AccountNo { get; set; }
public string AuthValue { get; set; }
}
in AuthValue it gives me output as {\"TopUpMobileNumber\":\"345234533466\",\"VoucherAmount\":\"100\"} which is absolutely correct. now i want to modify my class in such way that i want AuthValue in string format as well and in seprate member variable format.
so i modify my class in this way but it gives error
public class UserContext
{
public string AccountNo { get; set; }
public string AuthValue { get; set; }
public Auth ????? { get; set; }
}
public class Auth
{
public string TopUpMobileNumber { get; set; }
public string VoucherAmount { get; set; }
}
My requirement is
AuthValue whole json string i required
in another variable i want member wise values
Parsing Logic
UserContext conObj1 = new UserContext();
conObj1 = JsonConvert.DeserializeObject<UserContext>(context);
Note : No modification in json string is allowed.
I'm not very familiar with JsonConvert or Json.NET so I'm not sure what options are available for that. Personally I'd just call the deserializer again immediately afterwards.
UserContext conObj1 = new UserContext();
conObj1 = JsonConvert.DeserializeObject<UserContext>(context);
conObj1.AuthObject = JsonConvert.DeserializeObject<Auth>(conObj1.AuthValue);
You could move this into the class if you wanted and call it directly off the deserialized class.
public class UserContext
{
public string AccountNo { get; set; }
public string AuthValue { get; set; }
public Auth AuthObject { get; private set; }
internal UserContext Deserialize()
{
// Serialize the object
this.AuthObject = JsonConvert.DeserializeObject<Auth>(this.AuthValue);
// Return this object for a simple single-line call.
return this;
}
}
// Single object
UserContext conObj1 = new UserContext();
conObj1 = JsonConvert.DeserializeObject<UserContext>(context).Deserialize();
// Enumeration of object (given that this is supported in JsonConvert)
IEnumerable<UserContext> conObjs = JsonConvert.DeserializeObject<IEnumerable<UserContext>(contexts).Select(c => c.Deserialize()).ToList();
Or if you feel self hating you could go as far as doing the deserialization at the time the property is accessed (although I would avoid this at almost all costs due to the numerous issues it can cause).
public class UserContext
{
private Auth m_auth;
public string AccountNo { get; set; }
public string AuthValue { get; set; }
public Auth AuthObject
{
get
{
if (this.m_auth == null)
{
this.m_auth = JsonConvert.DeserializeObject<Auth>(this.AuthValue);
}
return this.m_auth;
}
}
}
I would suggest using two classes - one for the JSON you're actually receiving, and then one for the object model you want to use:
public class JsonUserContext
{
public string AccountNo { get; set; }
public string AuthValue { get; set; }
}
public class UserContext
{
public string AccountNo { get; set; }
public Auth AuthValue { get; set; }
}
public class Auth
{
public string TopUpMobileNumber { get; set; }
public string VoucherAmount { get; set; }
}
...
var jsonUserContext = JsonConvert.DeserializeObject<JsonUserContext>(json);
var authJson = jsonUserContext.AuthValue;
var userContext = new UserContext {
AccountNo = jsonUserContext.AccountNo,
AuthValue = JsonConvert.DeserializeObject<JsonUserContext>(authJson);
};

Model property initialization

I have this model class "UserProfile", it's the original UserProfile class of Membership with a few added properties and methods.
[Table("UserProfile")]
public class UserProfile
{
public UserProfile()
{
this.DictionaryFrom = "eng";
this.DictionaryTo = "hun";
this.trainingType = "normal";
}
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string DictionaryFrom { get; set; }
public string DictionaryTo { get; set; }
public string trainingType { get; set; }
public virtual ICollection<ForeignExpression> learnedexpressions { get ; set ; }
}
My problem is that upon registering a new user, the three fields in the constructor don't get the values assigned to them (so, there's a NULL in the database for each of them).
The user can set them by choosing values from a list, but I'd like to have a default value for all of them. What am I doing wrong?
Not being a C# aficionado, I'd do something like this... there's probably a "better" way of doing it.
private string myValue = "default value";
public string MyValue {
get { return myValue; }
set {
if (null != value) { myValue = value; }
}
}

DTO changes to null after being transfered from the client to the server

I have a very strange problem: The instance of my DTO that is non-null on the client side is received as null on the server side. Any ideas what could cause this? I don't even know where I should start looking...
Some code (this is exactly the code I am executing):
Client side:
public class AuthenticatedUser
{
private readonly UserDto _user;
// ...
public bool SetNewPassword(string oldPasswordHash, string newPasswordHash)
{
using (var userService = new UserServiceClient())
{
if(_user == null)
throw new InvalidOperationException("Client side");
return userService.SetNewPassword(_user, oldPasswordHash,
newPasswordHash);
}
}
}
The class UserDto has automatically been created when I added the service reference.
Server side:
public class UserService : IUserService
{
// ...
public bool SetNewPassword(UserDto userDto, string oldPasswordHash,
string newPasswordHash)
{
using (var unitOfWork = _unitOfWorkFactory.Start())
{
if (userDto == null)
throw new InvalidOperationException("Server side");
var user = unitOfWork.Repository.Get<User>()
.ByUserNameAndPasswordHash(userDto.UserName,
oldPasswordHash);
if (user == null)
return false;
user.PasswordHash = newPasswordHash;
return true;
}
}
}
I am getting the InvalidOperationException with the text "Server side"...
UPDATE:
The UserDto class on the server side looks like this:
public class UserDto
{
public UserDto() {}
public UserDto(User domainObject)
{
Mapper.Map(domainObject, this);
}
public String AcademicDegree { get; set; }
public String EmailAddress { get; set; }
public String FirstName { get; set; }
public Gender Gender { get; set; }
public Boolean HasChangedPassword { get; set; }
public Int32 Id { get; set; }
public Boolean IsActive { get; set; }
public String LastName { get; set; }
public IEnumerable<MailboxDto> Mailboxes { get; set; }
public String PasswordHash { get; set; }
public String PronunciationOfName { get; set; }
public String Role { get; set; }
public IList<ScheduledGreetingDto> ScheduledGreetings { get; set; }
public LanguageDto SpeakerLanguage { get; set; }
public String Title { get; set; }
public String UserName { get; set; }
}
Interestingly the _user field on the client side I try to transmit is an instance the client got from the server via a call to another service method, i.e. transmitting the UserDto seems to work in general...
The most likely scenario is that the UserDto objects are not the same - namespace has changed, the properties do not match. If you're using generated proxies, try Update Service Reference... to make sure client and server are in sync.
You might want to use Fiddler to see what's being sent between the two applications. This will let you check whether it's a serialization issue (the client isn't correctly sending the data) and a de-serialization issue (the server isn't correctly receiving the data).

Categories