.NET Core Code First error on nullable object - c#

This is my logs table:
public class Logs
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int id { get; set; }
public DateTime Date { get { return DateTime.Now; } }
public string Controller { get; set; }
public string Action { get; set; }
public string Text { get; set; }
public bool isError {
get {
return this._isError.HasValue ? this._isError.Value : false;
}
set {
this._isError = value;
this.isError = value;
}
}
private bool? _isError = null;
}
and I don't know why when I try to make an insert, like:
var log = new Logs();
log.Action = "Send";
log.Controller = "Home";
log.Text = msg;
_context.logs.Add(log);
I get this error:
System.InvalidOperationException: 'Nullable object must have a value.'
And this is the object:
Except that private _isError variable, all the database columns have a value.
Where is the error?

Why is your private property nullable and your public property is not?
I would remove your private property and then change your public property:
public bool IsError { get; set; }
Since you're never going to return 'null' anyway, why would you make it an option?
Edit:
I also think this will cause an endless loop of your IsError property to be set:
set {
this._isError = value;
this.isError = value;
}
You're setting the public property within the public property setter.
Only setting the private property here is enough since you return the value of the private property in your getter.
This is just a side note though, I would still remove the private property and just use
public bool IsError { get; set; }

Related

Assigning [NotMapped] property value after "regular" (mapped) property value has been assigned

Is there a way to assign a value to a not mapped property after all mapped properties get their values from the DB? For example:
public class ProcessSupervisor
{
public int ID { get; set; }
public int MaximumConcurrentProcesses { get; set; }
[NotMapped]
public int AvailableProcessSlots { get; set; }
}
I would like to keep the value of MaximumConcurrentProcesses in the database and assign that value to AvailableProcessSlots as a default value once Entity Framework instantiates ProcessSupervisor DBSet and assigns corresponding values to objects properties. Obviously I cannot assign the value of MaximumConcurrentProcesses to AvailableProcessSlots in class constructor since MaximumConcurrentProcesses hasn't received it's value from database yet. Is there a proper way do do it without initializing the AvailableProcessSlots value in some weird and awkward way?
You can try something like this:
public class ProcessSupervisor
{
public int ID { get; set; }
public int MaximumConcurrentProcesses { get; set; }
[NotMapped]
private int? availableProcessSlots = null;
public int AvailableProcessSlots
{
get
{
return availableProcessSlots ?? MaximumConcurrentProcesses;
}
set
{
availableProcessSlots = value;
}
}
}

c# Generic property

I am trying to make a class in C# that can be used to return data of any types.
public class ResponseObject
{
public <T> data { get;set }
public Boolean Success { get; set; }
public string Message { get; set; }
}
The Object will be a wrapper for the response object when my application sends a request to the API.
i have tried researching this but cannot find any tutorials which are relevant to what i am trying to do.
Is this possible in C#? the Response Object will be converted to a JSON string and then sent as a response.
I will not be doing any processing of this object as that will already by done. I just want to place the data inside the ResponseObject and send it
I want to do something along the lines of:
var customers = repository.GetCustomers();
var orders = repository.GetOrders();
if(customers)
{
success = true;
message = "";
}
else{
success = false;
message = "failed to get customers";
}
if(orders)
{
orderssuccess = true;
ordersmessage = "";
}
else{
orderssuccess = false;
ordersmessage = "failed to get orders";
}
ResponseObject customerResponse = new ResponseObject{
data = customers,
success = success,
message = message
};
ResponseObject orderResponse = new ResponseObject{
data = orders,
success = orderssuccess,
message = ordersmessage
};
You need to add <T> to the class and use T as the type of your property.
public class ResponseObject<T>
{
public T data { get; set; }
public Boolean Success { get; set; }
public string Message { get; set; }
}
You have almost done it already! Just change your <T> to T.
public class ResponseObject<T> where T : class
{
public T data { get; set; }
public Boolean Success { get; set; }
public string Message { get; set; }
}
Here where T : class ensure that the generic type parameter is a reference type. From your question it seems you are going to pass in an object there.
You have two options here:
Make the class generic, or
Use generic methods for accessing the property
Here are the examples of both approaches:
// Make the class generic
public class ResponseObject<T> {
public T Data { get; set }
public Boolean Success { get; set; }
public string Message { get; set; }
}
// Use generic methods to access the property
public class ResponseObject {
private object data;
public T GetData<T>() {
return (T)data;
}
public void SetData<T>(T newData) {
data = newData;
}
public Boolean Success { get; set; }
public string Message { get; set; }
}
Second approach is less robust than the first one - basically, it's a glorified unrestricted cast. First approach, however, does not let you build a container of ResponseObjects with different Ts. You can address this problem by adding an interface on top of ResponseObject:
interface IResponseObject {
object DataObj { get; set }
Type ObjType { get; }
bool Success { get; set; }
string Message { get; set; }
}
public class ResponseObject<T> {
public T Data { get; set }
public ObjType => typeof(T);
public DataObj {
get => Data;
set => Data = value; // C# 7 syntax
}
public Boolean Success { get; set; }
public string Message { get; set; }
}

ViewModel properties for properties of nested classes inside the model

I have an application following the MVVM pattern, that has to serialize XML files. As some of the XML attributes are nested, I've created nested classes inside my Model, like this:
public class OPER_FILE
{
public UNB unb { get; set; }
public OPER oper { get; set; } //nested class, level 1
public OPER_FILE()
{
unb = new UNB();
oper = new OPER();
}
}
public class OPER
{
public UNH unh { get; set; } //these are all nested classes, level 2
public UVT uvt { get; set; }
public VIN vin { get; set; }
public OPER()
{
unh = new UNH();
uvt = new UVT();
}
}
#region "nested classes"
public class UNB
{
public string unb { get; set; }
public string unb_2 { get; set; }
}
public class UNH
{
public string unh { get; set; }
public string unh_2 { get; set; }
}
public class UVT
{
public string uvt { get; set; }
public string uvt_1 { get; set; }
public string uvt_2 { get; set; }
}
public class VIN
{
public string vin { get; set; }
public string vin_1 { get; set; }
public string vin_2 { get; set; }
public string vin_3 { get; set; }
public string vin_4 { get; set; }
}
#endregion
The attributes of the nested classes are all strings, because this simplifies the XML serialization for now (I'm still in the conception phase).
In my corresponding ViewModel, I've simply created a property for the nested class inside the model, so I can access all of the nested properties with just referring to this nested class from the ViewModel.
public class OPERViewModel : IViewModelBase
{
private OPER_FILE Model;
public UNB unb
{
get
{ return Model.unb;}
set
{ Model.unb = value; }
}
public OPER oper
{
get
{ return Model.oper; } //this is the tricky part, by now I'm just referring to the nested class as a property of the model
set
{ Model.oper = value; }
}
public OPERViewModel()
{ Model = new OPER_FILE(); }
}
The question is, however, that I want to display some of the properties not as strings but as boolean values using checkboxes on the UI.
Saying I want to display Model.oper.vin.vin_1 as boolean (where the ViewModel should manage the conversion from string to bool in the getter of its own property reflection of Model.oper.vin.vin_1), how would I do that?
Would I really have to implement every nested property from a nested class as an own property of the ViewModel (like stated below) to gain control over the way it will be returned to the UI?
//ViewModel-implementation with type-conversion of a property from a nested class of the model
//this would get bind to the UI instead of Model.oper.vin.vin_1
public bool vin_1
{
get
{
if (Model.oper.vin.vin_1 == "1")
{ return true; }
else
{ return false; }
}
set
{
if (value)
{ Model.oper.vin.vin_1 = "1"; }
else
{ Model.oper.vin.vin_1 = "0"; }
}
}
I hope there is a better solution out there...
Edit:
What I forgot to mention before, there're not only strings that have to be displayed as booleans, also DateTime-values that should be displayed as a DatePicker-control, integer-values that I would like to have as NumberPickers and so on.
The xml-file, on the other hand, will be consumed by an interface with some pretty fixed regulations that i need to match, such a dynamically leading zeros on both integer- and float-values, special date formats and commas instead of dots as decimal separators. So sticking with the string-values inside the object to serialize is a good way of maintaining control over how the values would get actually parsed inside the xml-file.
I'll try and experiment with some different converters, as #BrandlyDOTNet reommended, but are still curious about how this could be solved in another way.
There's a different solution out there, namely that you can use a converter to define the translation between your strings and a bool.
Something like:
public class StringToBoolConverter : IValueConverter
{
public object Convert(...)
{
return value.ToString() != "0";
}
public object ConvertBack(...)
{
bool boolVal = (bool)value;
return boolVal ? "1" : "0";
}
}
Usage:
<CheckBox IsChecked={Binding SomeProp, Converter={StaticResource StringToBoolConverter}"/>
But to answer your deeper question, no, the framework will not just convert the string "1" into a bool. Moreover, you can strongly type your object that is being serialized, so none of this is actually necessary.

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; }
}
}

Custom Validation Attribute is not called ASP.NET MVC

Hello everyone I have create custom validation attribute and assign it to class level validation. Unfortunately, it is not called. I try every way that it think it could be solve the problem. However, it take me for hours and I can't find the attribute is not called by validation mechanism.
For illustrate you I put the following code.
Attribute
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public sealed class BooleanDependencyAttribute : ValidationAttribute
{
private const string _defaultErrorMessage = "กรุณากรอก{0}";
private readonly object _typeId = new object();
public string DependencyPropertyName { get; private set; }
public string DependentPropertyName { get; private set; }
public BooleanDependencyAttribute(string dependencyPropertyName, string dependentPropertyName)
: base(_defaultErrorMessage)
{
DependencyPropertyName = dependencyPropertyName;
DependentPropertyName = dependentPropertyName;
}
public override object TypeId
{
get
{
return _typeId;
}
}
public override string FormatErrorMessage(string name)
{
return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString,name);
}
public override bool IsValid(object value)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value);
bool dependencyValue = (bool) properties.Find(DependencyPropertyName, true /* ignoreCase */).GetValue(value);
object dependentValue = properties.Find(DependentPropertyName, true /* ignoreCase */).GetValue(value);
if (dependencyValue)
{
return true;
}
else
{
if (dependentValue == null)
{
return false;
}
else
{
return true;
}
}
}
}
ViewModel
[BooleanDependency("ReleaseNow","ReleaseDate",ErrorMessage="Please enter release date")]
public class ContentCreate
{
public string Title { get; set; }
public DateTime? ReleaseDate { get; set; }
public string Details { get; set; }
public string Abstract { get; set; }
public string Tags { get; set; }
public bool ReleaseNow { get; set; }
}
Please could you help me to solve this problem.
I found the solution. In fact validation in class level is called after all property-level validations are valid. Therefore I need to complete other required property then BooleanDependencyAttribute will called and valid value.
Thanks for view, edit the title and tag.

Categories