Is it possible in C# to collect information in an enum instead of a dedicated class?
Example how it would work in Java:
public enum Action {
JUMP( "JUMP", 1),
CROUCH ("CROUCH", 2),
;
private String animationId;
private int buttonId;
private Action( String animationId, int buttonId) {
this.animationId = animationId;
this.buttonId = buttonId;
}
public String getAnimationId() {
return animationId;
}
public int getButtonId() {
return buttonId;
}
}
You can use enum with attributes:
public enum Action{
[MyValue("JUMP", 1)]
JUMP,
[MyValue("CROUCH", 2)]
CROUCH
}
[AttributeUsage(
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
public class MyValueAttribute : System.Attribute{
public string Value{get; private set}
public string AnimationId{get; private set;}
public MyValueAttribute(string animationId, string value){
AnimationId = animationId;
Value = value;
}
and you can get value as follows:
public static class EnumExtensions{
public static string GetValue(this Enum value)
{
var type = value.GetType();
var name = Enum.GetName(type, value);
if (name == null) return string.Empty;
var field = type.GetField(name);
if (field == null) return string.Empty;
var attr = Attribute.GetCustomAttribute(field, typeof(MyValueAttribute)) as MyValueAttribute;
return attr != null ? attr.Value: string.Empty;
}
public static string GetAnimationId(this Enum value)
{
var type = value.GetType();
var name = Enum.GetName(type, value);
if (name == null) return string.Empty;
var field = type.GetField(name);
if (field == null) return string.Empty;
var attr = Attribute.GetCustomAttribute(field, typeof(MyValueAttribute)) as MyValueAttribute;
return attr != null ? attr.AnimationId: string.Empty;
}
}
Usage:
Action.JUMP.GetValue();
Action.JUMP.GetAnimationId();
or you can use one method which return for example Tuple with AnimationId and Value
No, but you can use static class fields instead:
public sealed class Action
{
public static readonly Action JUMP = new Action("JUMP", 1);
public static readonly Action CROUCH = new Action("CROUCH", 2);
public string AnimationId { get; }
public int ButtonId { get; }
private Action(String animationId, int buttonId)
{
AnimationId = animationId;
ButtonId = buttonId;
}
public override string ToString() => AnimationId;
}
You could definitely use attributes like suggested. However, you can call .ToString() on an enum value to get its name as a string value, and you can also assign int values to them. By default they are assigned 0-X based on index. However you could do this
public enum Action {
JUMP=1,
CROUCH=2
}
And then to access these values
Action action = Action.JUMP;
int value = (int) action; //Is set to 1
string name = action.ToString(); //Is set to "JUMP"
While this certainly will not work in every case depending on how much you want your enum to store, for the situation you described this is much easier.
Related
Is it possible to add custom attribute on Class, that override all empty string properties? Something like this:
[DefaultValueForEmptyString(Text="N/A")]
public class PersonsDTO
{
public string Name { get; set; }
public string Lastname { get; set; }
public string Address { get; set; }
}
public class DefaultValueForEmptyString
{
public static void MapProperties(object Properties, string text)
{
foreach (var property in Properties)
{
if(string.IsNullOrEmpty(property))
{
property = text // "N/A in this case
}
}
}
}
To resolve a similar problem ages ago I implemented an extension to handle this :
public static string ValueOrDefault(this string value)
{
return string.IsNullOrWhiteSpace(value) ? "N/A" : value;
}
Now you can use this on all your string properties :
var person = new PersonsDTO();
//Prints N/A
Console.WriteLine(person.Name.ValueOrDefault());
That's not really impressive but the job is done.
Another option would be to make a custom string class that implicitly converts from your custom class to string and from a string to your custom class. It's a bit heavy handed, but so is making a custom attribute class.
I made a .NET fiddle showing an example of this here
A copy of the code is below in case .NET fiddle goes away.
using System;
public class DefaultString
{
private const string _default = "N/A";
public DefaultString(string normal)
{
Value = normal;
}
private string _value = _default;
public string Value
{
get
{
return _value;
}
set
{
if (String.IsNullOrEmpty(value))
_value = _default;
else
_value = value;
}
}
public bool IsDefault()
{
return Value == _default;
}
public override string ToString()
{
return Value;
}
public static implicit operator string(DefaultString defaultString)
{
if (defaultString == null)
return _default;
return defaultString.ToString();
}
public static implicit operator DefaultString(string normal)
{
return new DefaultString(normal);
}
}
public class Program
{
public static void Main()
{
DefaultString nullDefault = null;
DefaultString nullConstructorDefault = new DefaultString(null);
DefaultString emptyDefault = String.Empty;
DefaultString emptyConstructorDefault = new DefaultString(String.Empty);
DefaultString abcDefault = "abc";
DefaultString abcConstructorDefault = new DefaultString("abcConstructor");
Console.WriteLine("Default string assigned to null: " + nullDefault);
Console.WriteLine("Default string constructed with null: " + nullConstructorDefault);
Console.WriteLine("Default string assigned empty string: " + emptyDefault);
Console.WriteLine("Default string constructed with empty string: " + emptyConstructorDefault);
Console.WriteLine("Default string assigned \"abc\": " + abcDefault);
Console.WriteLine("Default string constructed with \"abcConstructor\": " + abcConstructorDefault);
}
}
The output should be:
Default string assigned to null: N/A
Default string constructed with null: N/A
Default string assigned empty string: N/A
Default string constructed with empty string: N/A
Default string assigned "abc": abc
Default string constructed with "abcConstructor": abcConstructor
public class UFMLine
{
public UFMTemplate elementTag;
public int posX1;
public int posY1;
public int posX2;
public int posY2;
public string property;
public string hierStr = string.Empty;
public List<UFMLine> ufmLines = new List<UFMLine>(); // the tricky nested class field
}
UFMLine ufmobj = new UFMLine();
This ufmobj is populated perfectly at the window load.
In my button click of wpf window xaml code behind...
string nthItem = "ufmobj.ufmLines[0].ufmLines[1].ufmLines[1].ufmLines[1].ufmLines[2].ufmLines[2].elementTag";
// Tried reflection method, but giving null exception
var result = typeof(UFMLine).GetField(nthItem).GetValue(ufmobj);
So when opening watch window and fetch the value for nthItem name it gives appropriate value.
How to get it in the code behind or am i not properly using the reflection?
Thanks.
The "name" of the variable (ufmobj) could be a problem since it could be lost in a release build, but the rest can be achieved with reflection if you don't mind implementing your own parser.
Split path (Syntax of your choice)
Resolve one path segment after another
Determine if path is Field/Property/Indexer/Method/etc.
Repeat until done
Here is a small snippet to get you going (far from complete, but works with your example):
Resolve a single Field or Property
private object GetFieldOrProperty(object obj, string name)
{
Type objType = obj.GetType();
if (objType.GetField(name) != null)
return objType.GetField(name).GetValue(obj);
if (objType.GetProperty(name) != null)
return objType.GetProperty(name).GetValue(obj, null);
return null;
}
Resolve the entire path:
private object Resolve(object parent, string path)
{
string[] paths = path.Split('.');
foreach (string p in paths)
{
if (p.EndsWith("]"))
{
int start = p.IndexOf("[");
string property = p.Substring(0, start);
string index = p.Substring(start + 1, p.Length - start - 2);
parent = GetFieldOrProperty(parent, property);
if (parent == null)
return null;
foreach (PropertyInfo info in parent.GetType().GetProperties())
{
if (info.GetIndexParameters().Length < 1) continue;
parent = info.GetValue(parent, new object[] {int.Parse(index)});
break;
}
}
else
{
parent = GetFieldOrProperty(parent, p);
if (parent == null)
return null;
}
}
return parent;
}
Test case:
UFMLine ufmobj = new UFMLine();
ufmobj.ufmLines.Add(new UFMLine());
ufmobj.ufmLines[0].ufmLines.Add(new UFMLine());
ufmobj.ufmLines[0].ufmLines[0].ufmLines.Add(new UFMLine{property = "Success"});
Debug.WriteLine(Resolve("ufmLines[0].ufmLines[0].ufmLines[0].property.Length", ufmobj));
7 (length of "Success")
You may change the fields of your UFMLine class to public properties:
public class UFMLine
{
public UFMTemplate elementTag { get; set; }
public int posX1 { get; set; }
public int posY1 { get; set; }
public int posX2 { get; set; }
public int posY2 { get; set; }
public string property { get; set; }
public string hierStr { get; set; } = string.Empty;
public List<UFMLine> ufmLines { get; set; } = new List<UFMLine>();
}
Now you could use the part of your nthItem string after "ufmobj." as the Path of a Binding, for which you would use ufmobj as Source:
var binding = new Binding
{
Source = ufmobj,
Path = new PropertyPath("ufmLines[0].ufmLines[1].ufmLines[1].ufmLines[1].ufmLines[2].ufmLines[2].elementTag")
};
To make use of this Binding, you would also need a target dependency property, which you might declare in a helper class like this:
public class BindingHelper : DependencyObject
{
public static readonly DependencyProperty ResultProperty =
DependencyProperty.Register("Result", typeof(object), typeof(MainWindow));
public object Result
{
get { return GetValue(ResultProperty); }
set { SetValue(ResultProperty, value); }
}
}
Finally you would assign the Binding to the Target property and then retrieve the resulting value like this:
var bindingHelper = new BindingHelper();
BindingOperations.SetBinding(bindingHelper, BindingHelper.ResultProperty, binding);
var result = bindingHelper.Result;
i have an enum like
public enum DecimailPrecision
{
One,
Two,
}
and class as
class DecimailPrecision1
{
public const string One = "#,##0.0";
public const string Two = "#,##0.00";
}
i want to retrieve const string from class with enum. i already doing this with if and switch as
string format = string.Empty;
switch (value)
{
case DecimailPrecision.One:
format = DecimailPrecision1.One.ToString(); break;
case DecimailPrecision.Two:
format = DecimailPrecision1.Two.ToString(); break;
default:
format = DecimailPrecision1.Two.ToString(); break;
}
if (value == "One"){
format = DecimailPrecision1.One.ToString();}
else if (value == "Two"){
format = DecimailPrecision1.Two.ToString();}
}
i need a better way because i have lot items in enum.
thanks.
Why not just create a Dictionary<DecimailPrecision, string> and hold the mappings in that?
That way you can simply look up your DecimailPrecision value in the dictionary and retrieve the appropriately mapped string.
You could even store the mapping in config and read it from that, so you wouldn't need to recompile your code to add new mappings.
To explicitly apply this to your code (I'd recommend changing the name of your consts to DecimalPrecisionFormat):
var precisionMap = new Dictionary<DecimailPrecision, string>
{
{ DecimailPrecision.One, DecimailPrecision1.One }
, { DecimailPrecision.Two, DecimailPrecision1.Two }
};
var formatTwo = precisionMap[DecimailPrecision.Two];
For similar needs we developed a custom attribute and a few extension methods.
Usage is like this.
public enum DecimailPrecision
{
[EnumCode("#,##0.0")]
One,
[EnumCode("#,##0.00")]
Two
}
string format = DecimailPrecision.One.GetCode();
It may be meaningless for your case but reverse is valid through like this
string format ="#,##0.00";
DecimailPrecision dp = format.ToEnum<DecimailPrecision>();
Extensions and Atrribute are like:
public static class EnumExtensions
{
private static readonly Dictionary<Type, EnumCodePair[]> EnumCodeCache = new Dictionary<Type, EnumCodePair[]>();
public static string GetCode(this Enum enumValue) {
var codePairs = GetEnumCodePairs(enumValue.GetType());
return codePairs.First(cp => Equals(cp.Enum, enumValue)).Code;
}
public static T ToEnum<T>(this string enumCode) {
var codePairs = GetEnumCodePairs(typeof(T));
return (T)codePairs.First(cp => Equals(cp.Code, enumCode)).Enum;
}
private static IEnumerable<EnumCodePair> GetEnumCodePairs(Type type) {
if(!EnumCodeCache.ContainsKey(type)) {
var enumFields = type.GetFields(BindingFlags.Public | BindingFlags.Static);
var codePairs = new List<EnumCodePair>();
foreach(var enumField in enumFields) {
var enumValue = Enum.Parse(type, enumField.Name);
var codePair = new EnumCodePair {
Enum = enumValue
};
var attrs = enumField.GetCustomAttributes(typeof(EnumCodeAttribute), false);
codePair.Code = attrs.Length == 0
? enumField.Name
: ((EnumCodeAttribute)attrs[0]).Code;
codePairs.Add(codePair);
}
EnumCodeCache.Add(type, codePairs.ToArray());
}
return EnumCodeCache[type];
}
class EnumCodePair
{
public object Enum { get; set; }
public string Code { get; set; }
}
}
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class EnumCodeAttribute : Attribute
{
public EnumCodeAttribute(string code) {
Code = code;
}
public string Code { get; private set; }
}
My first approach looked like it would work very nicely until I got a runtime error I had no idea how to solve at var name = ((LCData)attributes[0]).Name; about index out of range. Practically I was just copying the code I found at Getting attributes of Enum's value so I was not 100% sure what it actually did. So when the following code didn't work, I moved on to another solution.
public enum Identification : ushort
{
[LCAttribute("IMG_BG01_Greens")]
BG01_Greens = 0,
[LCAttribute("Rabbit", "IMG_E01_Rabbit")]
ENEMY_E01_Rabbit = 2000,
}
public static class Enums
{
public static LCData GetInfo(Identification id)
{
var type = typeof(Identification);
var memInfo = type.GetMember(id.ToString());
var attributes = memInfo[0].GetCustomAttributes(typeof(LCData), false);
var name = ((LCData)attributes[0]).Name;
var tex = ((LCData)attributes[0]).Texture;
LCData data;
data.Name = name;
data.Texture = tex;
return data;
}
}
public struct LCData
{
public string Name;
public string Texture;
public LCData(Identification id)
{
this = Enums.GetInfo(id);
}
}
public class LCAttribute : System.Attribute
{
private string _Name;
public string Name
{
get
{
return _Name;
}
}
private string _Texture;
public string Texture
{
get
{
return _Texture;
}
}
public LCAttribute(string texture)
{
_Texture = texture;
}
public LCAttribute(string name, string texture)
{
_Name = name;
_Texture = texture;
}
}
Secondly I tried the typesafe enum approach. This had 2 fatal weaknesses I couldn't find a solution for:
1) I cannot get a list of available enum entries for looping operations.
2) I cannot get the corresponding enum entry by an id number.
public sealed class Identification
{
private readonly ushort _ID;
private readonly string _Name;
private readonly string _Tex;
public static readonly Identification BG01_Greens = new Identification(0, "IMG_BG01_Greens");
public static readonly Identification ENEMY_E01_Rabbit = new Identification(2000, "Rabbit", "IMG_E01_Rabbit");
private Identification(ushort id, string tex)
{
_ID = id;
_Tex = tex;
}
private Identification(ushort id, string name, string tex)
{
_ID = id;
_Name = name;
_Tex = tex;
}
public ushort ID { get { return _ID; } }
public string Name { get { return _Name; } }
public string Texture { get { return _Tex; } }
}
How should I proceed? Why doesn't my first solution work?
You are confusing LCData and LCAttriubte. Because LCAttribute is a valid attribute, but you are trying to use LCData as the attribute. (By the way, probably you don't need two separate types... but I bear with you).
This the ammended code:
public enum Identification : ushort
{
[LCAttribute("IMG_BG01_Greens")] //Look the type of the attributes is LCAttribute
BG01_Greens = 0,
[LCAttribute("Rabbit", "IMG_E01_Rabbit")]
ENEMY_E01_Rabbit = 2000,
}
public static class Enums
{
public static LCData GetInfo(Identification id)
{
var type = typeof(Identification);
var memInfo = type.GetMember(id.ToString());
//this will return an array of LCAttributes
var attributes = memInfo[0].GetCustomAttributes(typeof(LCAttribute), false);
//I tell you they are LCAttribute not LCData
var name = ((LCAttribute)attributes[0]).Name;
var tex = ((LCAttribute)attributes[0]).Texture;
//If the above were an LCData why would create a new one here? [Rethorical]
LCData data;
data.Name = name;
data.Texture = tex;
return data;
}
}
Note: For altenatives approaches and maybe some insight into this approach you can see my answer to How do you make an 'enum' that has data tied to it?. The approach you use here is listed under "Custom Attributes".
I am not sure if this is possible but I want to iterate through a class and set a field member property without referring to the field object explicitly:
public class Employee
{
public Person _person = new Person();
public void DynamicallySetPersonProperty()
{
MemberInfo[] members = this.GetType().GetMembers();
foreach (MemberInfo member in members.Where(a => a.Name == "_person"))
//get the _person field
{
Type type = member.GetType();
PropertyInfo prop = type.GetProperty("Name"); //good, this works, now to set a value for it
//this line does not work - the error is "property set method not found"
prop.SetValue(member, "new name", null);
}
}
}
public class Person
{
public string Name { get; set; }
}
In the answer that I marked as the answer you need to add:
public static bool IsNullOrEmpty(this string source)
{
return (source == null || source.Length > 0) ? true : false;
}
Here's a complete working example:
public class Person
{
public string Name { get; set; }
}
class Program
{
static void PropertySet(object p, string propName, object value)
{
Type t = p.GetType();
PropertyInfo info = t.GetProperty(propName);
if (info == null)
return;
if (!info.CanWrite)
return;
info.SetValue(p, value, null);
}
static void PropertySetLooping(object p, string propName, object value)
{
Type t = p.GetType();
foreach (PropertyInfo info in t.GetProperties())
{
if (info.Name == propName && info.CanWrite)
{
info.SetValue(p, value, null);
}
}
}
static void Main(string[] args)
{
Person p = new Person();
PropertySet(p, "Name", "Michael Ellis");
Console.WriteLine(p.Name);
PropertySetLooping(p, "Name", "Nigel Mellish");
Console.WriteLine(p.Name);
}
}
EDIT: added a looping variant so you could see how to loop through property info objects.
public class Person
{
public string Name { get; set; }
}
public class Employee
{
public Person person = new Person();
public void DynamicallySetPersonProperty()
{
var p = GetType().GetField("person").GetValue(this);
p.GetType().GetProperty("Name").SetValue(p, "new name", null);
}
}
With the following Extension methods that I have created, you can set or get any property value even if they are nested
GetPropertyValue(customObject, "Property.Nested.Child.Name");
or set
SetPropertyValue(customObject, "Property.Nested.Child.Name", "my custom name");
private class TargetProperty
{
public object Target { get; set; }
public PropertyInfo Property { get; set; }
public bool IsValid { get { return Target != null && Property != null; } }
}
private static TargetProperty GetTargetProperty(object source, string propertyName)
{
if (!propertyName.Contains("."))
return new TargetProperty { Target = source, Property = source.GetType().GetProperty(propertyName) };
string[] propertyPath = propertyName.Split('.');
var targetProperty = new TargetProperty();
targetProperty.Target = source;
targetProperty.Property = source.GetType().GetProperty(propertyPath[0]);
for (int propertyIndex = 1; propertyIndex < propertyPath.Length; propertyIndex++)
{
propertyName = propertyPath[propertyIndex];
if (!string.IsNullOrEmpty(propertyName))
{
targetProperty.Target = targetProperty.Property.GetValue(targetProperty.Target, null);
targetProperty.Property = targetProperty.Target.GetType().GetProperty(propertyName);
}
}
return targetProperty;
}
public static bool HasProperty(this object source, string propertyName)
{
return GetTargetProperty(source, propertyName).Property != null;
}
public static object GetPropertyValue(this object source, string propertyName)
{
var targetProperty = GetTargetProperty(source, propertyName);
if (targetProperty.IsValid)
{
return targetProperty.Property.GetValue(targetProperty.Target, null);
}
return null;
}
public static void SetPropertyValue(this object source, string propertyName, object value)
{
var targetProperty = GetTargetProperty(source, propertyName);
if(targetProperty.IsValid)
{
targetProperty.Property.SetValue(targetProperty.Target, value, null);
}
}
And here are a couple of tests for it
[TestFixture]
public class ObjectExtensionsTest
{
private class MockClass
{
public MockClass()
{
Nested = new NestedMockClass();
}
public string Id { get; set; }
public string Name { get; set; }
public string GetOnly { get { return "MockClass"; } }
public string SetOnly { set { } }
public NestedMockClass Nested { get; set; }
}
private class NestedMockClass
{
public string NestedId { get; set; }
public string NestedName { get; set; }
public string NestedGetOnly { get { return "NestedMockClass"; } }
public string NestedSetOnly { set { } }
}
[Test]
public void TestShouldFindProperty()
{
MockClass mockObject = new MockClass();
Assert.IsTrue(mockObject.HasProperty("Id"));
Assert.IsTrue(mockObject.HasProperty("Name"));
Assert.IsTrue(mockObject.HasProperty("GetOnly"));
Assert.IsTrue(mockObject.HasProperty("SetOnly"));
Assert.IsTrue(mockObject.HasProperty("Nested"));
Assert.IsTrue(mockObject.HasProperty("Nested.NestedId"));
Assert.IsTrue(mockObject.HasProperty("Nested.NestedName"));
Assert.IsTrue(mockObject.HasProperty("Nested.NestedGetOnly"));
Assert.IsTrue(mockObject.HasProperty("Nested.NestedSetOnly"));
}
[Test]
public void TestShouldGetPropertyValue()
{
MockClass mockObject = new MockClass();
mockObject.Id = "1";
mockObject.Name = "Name";
mockObject.Nested.NestedId = "NestedId";
mockObject.Nested.NestedName = "NestedName";
Assert.AreEqual(mockObject.Id, mockObject.GetPropertyValue("Id"));
Assert.AreEqual(mockObject.Name, mockObject.GetPropertyValue("Name"));
Assert.AreEqual(mockObject.GetOnly, mockObject.GetPropertyValue("GetOnly"));
Assert.AreEqual(mockObject.Nested.NestedId, mockObject.GetPropertyValue("Nested.NestedId"));
Assert.AreEqual(mockObject.Nested.NestedName, mockObject.GetPropertyValue("Nested.NestedName"));
}
[Test]
public void TestShouldSetPropertyValue()
{
MockClass mockObject = new MockClass();
mockObject.SetPropertyValue("Id", "1");
mockObject.SetPropertyValue("Name", "Name");
mockObject.SetPropertyValue("Nested.NestedId", "NestedId");
mockObject.SetPropertyValue("Nested.NestedName", "NestedName");
Assert.AreEqual(mockObject.Id, "1");
Assert.AreEqual(mockObject.Name, "Name");
Assert.AreEqual(mockObject.Nested.NestedId, "NestedId");
Assert.AreEqual(mockObject.Nested.NestedName, "NestedName");
}
}
Hope you find it useful.
You are trying to set the Name property of your Employee class's _person field. It doesn't have one. Try this:
prop.SetValue(((FieldInfo)member).GetValue(this), "new name", null)
Not sure if you need to cast the first argument like this:
prop.SetValue((Person)((FieldInfo)member).GetValue(this), "new name", null)
This then applies it to the value of the _person field instead.
You a trying to perform SetValue() on the property Name of the variable member that is a MemberInfo object and this proeprty is read only.
Note you do not need to iterate over all memebers and you do not need to get the field _person with reflection as it is defined in the same class as the method DynamicallySetPersonProperty().
So the code shoul read like this.
PropertyInfo property = this._person.GetType().GetProperty("Name");
property.SetValue(this._person, "new name", null);
The first line will fail if _person is null. So you can use reflectiopn to get the type of the field.
FieldInfo field = this.GetType().GetField("_person", BindingFlags.Public);
PropertyInfo property = field.FieldType.GetProperty("Name");
But now accessing this property will still fail if _personis null.
property.Setvalue(field.GetValue(this), "new name", null);
try this:
public static void ApplyPropertyChanges(this object objDest, object objToCopyFrom)
{
if (objDest == null)
throw new ArgumentNullException();
if (objToCopyFrom == null)
throw new ArgumentNullException("objToCopyFrom");
if (objDest.GetType() != objToCopyFrom.GetType())
throw new Exception("Invalid type. Required: \"" + objDest.GetType().ToString() + "\"");
foreach (System.Reflection.PropertyInfo piOrig in objDest.GetType().GetProperties())
{
object editedVal = objToCopyFrom.GetType().GetProperty(piOrig.Name).GetValue(objToCopyFrom, null);
piOrig.SetValue(objDest,
editedVal,
null);
}
}
usage example:
public ActionResult Edit(Team editedTeamData)
{
if (!ModelState.IsValid)
return View();
Team origTeam = (from t in _db.Teams
where t.TeamID == editedTeamData.TeamID
select t).FirstOrDefault();
origTeam.ApplyPropertyChanges(editedTeamData);
_db.SubmitChanges();
return RedirectToAction("Index");
}