can not convert implicitly from string to int - c#

In C#, I have used Enum to get the drop down values:
class Enum
{
public enum Fields
{
AssignedTo = "Assigned To",
CloseReason = "Close Reason",
CustomerId = "Customer ID",
CustomerName = "Customer Name",
CompanyID = "Company ID",
CompanyName = "Company Name",
}
}
When I build the solution. I am getting the error: cannot implicitly convert type 'string' to 'int'.
I have removed the double quotes but still it shows the same error. What do I do wrong?

In C# string are not allowed types for enums.
Quote from MSDN https://msdn.microsoft.com/en-us/library/sbbt4032.aspx
The approved types for an enum are byte, sbyte, short, ushort, int,
uint, long, or ulong
If will have to do some kind of conversion (i.e. using [DisplayName] attribute) to use enum in dropdown.

i am not sure if it is because you are trying to display string to the enum then is because enum only use int 16 and 32 so we have to create an extension to make it show strings and then use the int value to call it
using System.Reflection;
public static class EnumExtensions
{
public static string DisplayName(this Enum value)
{
FieldInfo field = value.GetType().GetField(value.ToString());
EnumDisplayNameAttribute attribute
= Attribute.GetCustomAttribute(field, typeof(EnumDisplayNameAttribute))
as EnumDisplayNameAttribute;
return attribute == null ? value.ToString() : attribute.DisplayName;
}
}
public class EnumDisplayNameAttribute : Attribute
{
private string _displayName;
public string DisplayName
{
get { return _displayName; }
set { _displayName = value; }
}
}
class Enum
{
public enum Fields
{
[EnumDisplayName(DisplayName = "Assigned To"
AssignedTo,
[EnumDisplayName(DisplayName = "Close Reason"
CloseReason,
[EnumDisplayName(DisplayName = "Customer ID"
CustomerId,
[EnumDisplayName(DisplayName = "Customer Name"
CustomerName,
[EnumDisplayName(DisplayName = "Company ID"
CompanyID,
[EnumDisplayName(DisplayName = "Company Name"
CompanyName ,
}
}
just like i did for my group description for listview

this is syntactically invalid in c#
https://msdn.microsoft.com/en-us/library/sbbt4032.aspx
you will need a workaround to create string enum in c#
https://www.google.com/?gfe_rd=cr&ei=sBwXV_XZDKO_wQOjmaqABw&gws_rd=ssl#q=string+enum+in+c%23

It is giving this error because by default the enum expects you to assign an integer value to the fields inside an enum.
public enum Fields
{
AssignedTo = 1,
CloseReason = 2,
CustomerId = 3,
CustomerName = 4,
CompanyID = 5,
CompanyName = 6
}
If you skip the assigning part , it will by default start assign the fields starting from integer 0.

I do not think you want to be using enum for a drop down. Try looking into Dictionary or DataTable or some other structures. Maybe we could help if you give us more detail about what exactly are you trying to do.
EDIT: Here is a simple example of using List<string> as data source for ComboBox
List<string> dsList = new List<string>();
dsList.Add("Assigned To");
dsList.Add("Close Reason");
dsList.Add("Customer ID");
dsList.Add("Customer Name");
dsList.Add("Company ID");
dsList.Add("Company Name");
comboBox1.DataSource = dsList;
Also, you can dynamicaly change the List based on what options you want to display to the user

Related

Check enum null when it is not nullable and do not have any null options

This is different from questions like below
How to tell if an enum property has been set? C#
I am working on creating WCF Rest service using existing DataContract classes. I cannot change property datatypes like enum to enum? and also cannot add new option in my enum like undefined, none, or by default set anything since if I do anyone of these changes it will be firm wide impact and many applications depend on it.
Normally people call my WCF REST Service using applications like POSTMAN where they send in json data like below in which Gender is an enum with Male, Female, Transgender, etc. If they do not send it my service throws exception and I want to add validation logic to check whether enum is null or not when QA scall my service using POSTMAN and send JSON data even though it is not nullable and also do not have any None, Null options in my enum? If it is NULL I want to send ArgumentNullException back to callers with nice message. I want to handle this situation gracefully.
public enum Gender
{
Male = 0,
Female = 1,
Transgender = 2
}
Below is good
{
"Name" : "XXX"
"Gender" : "1"
}
Below throws error
{
"Name" : "XXX"
"Gender" : ""
}
SOLUTION:
Thanks to p.s.w.g for pointing in correct direction and I marked his answer below. I am using Newtonsoft so I did like below
string stringfydata = Newtonsoft.Json.JsonConvert.SerializeObject(requestGender);
if(string.IsNullOrEmpty(stringfydata))
{
throw new ArgumentNullException("Gender value cannot be NULL or Empty.");
}
Other than the obvious option of warping the enum in a class, which might not work in your specific situation, you can set the enum variable to a integer out of the enum range. After that, you can then check to see if the integer is defined within the enum.
Since C# does not check enumerations, you can do the following:
public enum Gender
{
Male = 0,
Female = 1,
Transgender = 2
}
public int HandleGender(string strJsonGender){
if (strJsonGender == "")
{
return -1;
}
else {
// Get int representation of the gender
return (int)((Gender)Enum
.Parse(typeof(Gender),
strJsonGender, true));
}
}
public void MainMethod(string strJsonGender) {
Gender gVal;
int iVal = HandleGender(strJsonGender);
if (Enum.IsDefined(typeof(Gender), iVal))
{
// Handle if the an actual gender was specified
gVal = (Gender)iVal;
}
else {
// Handle "null" logic
}
Note: the answers below use DataContracts since you've indicated in your question, but similar solutions exist for Json.Net serialization.
You can use [DataMember(EmitDefaultValue = false)] to ignore cases where Gender is not specified at all. In this case, the value that's returned will be whatever enum member is assigned a value of 0 (note that if no member has that value, you'll still get a value of 0, which could be useful for you).
[DataContract]
class Person
{
[DataMember]
public string Name { get; set; }
[DataMember(EmitDefaultValue = false)]
public Gender Gender { get; set; }
}
void Main()
{
var json = "{\"Name\": \"XXX\"}";
var ser = new DataContractJsonSerializer(typeof(Person));
var obj = ser.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(json)));
obj.Dump(); // Person { Name = "XXX", Gender = Male }
}
To handle cases where an empty string is provided instead of a valid value or no value at all, you can use this hacky little trick:
[DataContract]
class Person
{
[DataMember]
public string Name { get; set; }
[IgnoreDataMember]
public Gender Gender
{
get
{
if (GenderValue.GetType() == typeof(string))
{
Enum.TryParse((string)GenderValue, out Gender result);
return result;
}
return (Gender)Convert.ToInt32(GenderValue);
}
set
{
GenderValue = value;
}
}
[DataMember(Name = "Gender", EmitDefaultValue = false)]
private object GenderValue { get; set; }
}
void Main()
{
var json = "{\"Name\": \"XXX\", \"Gender\": \"\"}";
var ser = new DataContractJsonSerializer(typeof(Person));
var obj = ser.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(json)));
obj.Dump(); // Person { Name = "XXX", Gender = Male }
}
However, this is somewhat awkward and can be easily abused. I'd recommend caution with this approach. As others have mentioned, we typically want to throw errors whenever invalid values are provided to a function / API. By 'failing fast' you let the user attempting to use the API know that they've constructed a request that's likely to produce unexpected results at some point.

Windows ComboBox Selected Item (populated from List<>)

I am setting a combobox item like this:
List<Object> items = new List<Object>();
items.Add(new { Text = "MyVal", Value = 1 });
cbo.DataSource = items;
It then in VS returns:
But I cannot simply now say cbo.SelectedItem.Text or cbo.SelectedItem.Value.
If i try this, I get the error
"object does not contain a definition for value and no extension method value
accepting a first argument of type object could be found"
How can I get the Value Property please
Based on great replies, I have now added this, to show that I cannot get the properties of Text or Value at all.
I've tried this code to pass the "string" into
public class ComboboxItem
{
public string Text { get; set; }
public short Value { get; set; }
public ComboboxItem(string t, short v)
{
Text = t;
Value = v;
}
}
The combo box is bound to a list containing anonymous types. You ought to use the dynamic keyword.
dynamic item = cbo.SelectedItem;
String text = item.Text;
Int32 value = item.Value;
You should add this.cbo.SelectedItem as object;
Then, for example:
public class student
{
public string name;
public int age;
}
var stu = cbo.SelectedItem as student;
string name = stu.name;
int age = stu.age;
OK,this is my first answer.
create class with Text and Value properties (ComboboxItem), then create the item list with that class. now you can do as below
ComboboxItem obj = cbo.SelectedItem as ComboboxItem;
//now you can get the obj.Value
I notice you're blanking out certain parts of your code, as of such I shall assume you're not using the object 'object' but something else, else your code wouldn't compile.
The ComboBox does not hold the datatype of its values, it all treats them as simple objects. So SelectedItem will be of type object, which should then be casted to the correct datatype in order to access the text / value property.
var myItem = cbo.SelectedItem as MyObject
if(myItem != null){
Console.WriteLine("Value is {0}", myItem.Value);
}

ServiceStack.Text.EnumMemberSerializer not working with Swagger plugin

I'm using ServiceStack v 3.9.71 and the ServiceStack.Text.EnumMemberSerializer assembly to serialize enums into readable text.
This works great, my enum values are serialized into the name I've specified using the EnumMemberAttribute.
The problem, though, is Swagger does not use my names. My guess is it just calls the .ToString() method on the enum values rather than the EnumMemberAttribute value.
Here is the order in which I setup the serialization. (In AppHost):
new EnumSerializerConfigurator()
.WithEnumTypes(new Type[] { typeof(MyEnum) })
.Configure();
Plugins.Add(new SwaggerFeature());
It doesn't seem to matter if the enum serializer is set before or after the swagger feature is added.
You are correct that the Swagger code does not use ServiceStack.Text.EnumMemberSerializer when parsing enum values. It only uses an Enum.GetValues here. Note that this is still the same in v4.
You can submit a pull request to make this change, but I'm not familiar with EnumMemberSerialzer and how it allows for retrieving the list of enum options. You may instead be able to use a string property decorated with ApiAllowableValues to achieve the affect.
Here is the solution I came up with (with the help of bpruitt-goddard, thanks mate):
The enum:
public enum MyEnum
{
[EnumMember(Value = "Value One")]
Value1 = 1,
[EnumMember(Value = "Value Two")]
Value2 = 2,
[EnumMember(Value = "Value Three")]
Value3 = 3
}
The client object:
public class MyClientObject
{
[Description("The name")]
public string Name {get;set;}
[Description("The client object type")]
[ApiAllowableValues("MyEnum", "Value One", "Value Two", "Value Three")]
public MyEnum MyEnum { get; set; }
}
Inside the AppHost:
new EnumSerializerConfigurator()
.WithEnumTypes(new Type[] { typeof(MyEnum) })
.Configure();
Now the enum is serialized properly and the Swagger documentation is correct. The only issue with this is having the names in two different places. Perhaps there is a way to check the names match via a unit test.
I came up with, in my opinion, a better solution. I wrote a class that extends the ApiAllowableValuesAttribute:
public class ApiAllowableValues2Attribute : ApiAllowableValuesAttribute
{
public ApiAllowableValues2Attribute(string name, Type enumType)
: base(name)
{
List<string> values = new List<string>();
var enumTypeValues = Enum.GetValues(enumType);
// loop through each enum value
foreach (var etValue in enumTypeValues)
{
// get the member in order to get the enumMemberAttribute
var member = enumType.GetMember(
Enum.GetName(enumType, etValue)).First();
// get the enumMember attribute
var enumMemberAttr = member.GetCustomAttributes(
typeof(System.Runtime.Serialization.EnumMemberAttribute), true).First();
// get the enumMember attribute value
var enumMemberValue = ((System.Runtime.Serialization.EnumMemberAttribute)enumMemberAttr).Value;
values.Add(enumMemberValue);
}
Values = values.ToArray();
}
}
The client object:
public class MyClientObject
{
[Description("The name")]
public string Name {get;set;}
[Description("The client object type")]
[ApiAllowableValues2("MyEnum", typeof(MyEnum))]
public MyEnum MyEnum { get; set; }
}
Now you don't have to specify the names again or worry about a name change breaking your Swagger documentation.

string.Format in Data Annotation Validation Attributes

Is there any way to set Data Annotation messages using formatted string instead of direct constant,
I need to set required field ErrorMessage like in following code, but it gives me an error.
[Required(ErrorMessage = string.Format(SystemMessages.Required, "First Name"))]
public string FirstName { get; set; }
SystemMessages is a constant file and it has following code,
public const string Required = "{0} is required.";
Is there any way to set attributes like this?
string.Format result is not a compile time constant and can't bee evaluated by the compiler. Attribute values are limited to
constant expression, typeof expression or array creation expression of an attribute parameter type.
More formally, you can find description of limitations at msdn. Formatting a string doesn't fit any of them, which are:
Simple types (bool, byte, char, short, int, long, float, and double)
string
System.Type
enums
object (The argument to an attribute parameter of type object must be a constant value of -one of the above types.)
One-dimensional arrays of any of the above types
At best you can try something similar to:
[Required(ErrorMessage = "First Name" + Required)]
public string FirstName { get; set; }
public const string Required = " is required.";
Just use DisplayAttribute, if you want to output display name instead of property name:
[Required]
[Display(Name = "First Name")]
public string FirstName { get; set; }
Please implement IValidatableObject which use Validate method. It will look like:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var memberNames = new List<string>();
if (string.IsNullOrEmpty(this.FirstName )
{
memberNames.Add("FirstName");
yield return new ValidationResult(string.Format(Resources.Required, "First Name"), memberNames);
}
}
If it is not clear please just read about IValidatableObject. Good luck!

How to read enum value in ASP.Net?

My enum structure is this
public enum UserRole
{
Administrator = "Administrator",
Simple_User = "Simple User",
Paid_User = "Paid User"
}
Now i want to read this enum value by using its name suppose
String str = UserRole.Simple_User;
it gives me "Simple User" in str instead of "Simple_User"
How we can do this???
You can do a friendly description like so:
public enum UserRole
{
[Description("Total administrator!!1!one")]
Administrator = 1,
[Description("This is a simple user")]
Simple_User = 2,
[Description("This is a paid user")]
Paid_User = 3,
}
And make a helper function:
public static string GetDescription(Enum en)
{
Type type = en.GetType();
MemberInfo[] info = type.GetMember(en.ToString());
if (info != null && info.Length > 0)
{
object[] attrs = info[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attrs != null && attrs.Length > 0)
{
return ((DescriptionAttribute)attrs[0]).Description;
}
}
return en.ToString();
}
And use it like:
string description = GetDescription(UserRole.Administrator);
Okay so by now you know that enum really is a list of numbers that you can give a handy string handle to like:
public enum ErrorCode
{
CTCLSM = 1,
CTSTRPH = 2,
FBR = 3,
SNF = 4
}
Also, as #StriplingWarrior showed, you can go so far by getting the enum string name and replacing underscores etc. But what I think you want is a way of associating a nice human string with each value. How about this?
public enum ErrorCode
{
[EnumDisplayName("Cataclysm")]
CTCLSM = 1,
[EnumDisplayName("Catastrophe")]
CTSTRPH = 2,
[EnumDisplayName("Fubar")]
FBR = 3,
[EnumDisplayName("Snafu")]
SNF = 4
}
Okay there's probably something in System.ComponentModel that does this - let me know. The code for my solution is here:
[AttributeUsage(AttributeTargets.Field)]
public class EnumDisplayNameAttribute : System.Attribute
{
public string DisplayName { get; set; }
public EnumDisplayNameAttribute(string displayName)
{
DisplayName = displayName;
}
}
And the funky Enum extension that makes it possible:
public static string PrettyFormat(this Enum enumValue)
{
string text = enumValue.ToString();
EnumDisplayNameAttribute displayName = (EnumDisplayNameAttribute)enumValue.GetType().GetField(text).GetCustomAttributes(typeof(EnumDisplayNameAttribute), false).SingleOrDefault();
if (displayName != null)
text = displayName.DisplayName;
else
text = text.PrettySpace().Capitalize(true);
return text;
}
So to get the human-friendly value out you could just do ErrorCode.CTSTRPH.PrettyFormat()
Hmm, enums can't have string values. From MSDN's Enum page:
An enumeration is a set of named constants whose underlying type is any integral type except Char.
To get the string version of the enum use the Enum's ToString method.
String str = UserRole.Simple_User.ToString("F");
I'm a little confused by your question, because C# doesn't allow you to declare enums backed by strings. Do you mean that you want to get "Simple User", but you're getting "Simple_User" instead?
How about:
var str = UserRole.Simple_User.ToString().Replace("_", " ");
You can do this by attribute, but really I think using an enum like this is possibly the wrong way to go about things.
I would create a user role interface that exposes a display name property, then implement that interface with a new class for each role, this also let's you add more behaviour in the future.
Or you could use an abstract class so any generic behaviour doesn't get duplicated...

Categories