I have following scenario:
public JsonResult ChangeFilterList(int option)
{
var data = new[] { new { Text = "Unknown option", Value = -1 } };
switch (option)
{
case 2: data = _departmentnameRepository.All.Select(x => new { Text = x.DeptName, Value = x.Id }).ToArray();
break;
case 3: data = Session["projectid"] == null
? _assetSequenceRepository.All.Select(x => new { Text = x.AssetShotName, Value = x.Id }).ToArray()
: _assetSequenceRepository.FindBy(p => p.ProjectId == (int)Session["projectid"]).Select(x => new { Text = x.AssetShotName, Value = x.Id }).ToArray();
break;
default: data = _userRepository.All.Select(x => new { Text = x.DisplayName, Value = x.UserID }).ToArray();
break;
}
return Json(data, JsonRequestBehavior.AllowGet);
}
case2
and default
looks great but complains on case 3 (conditional) saying: Cannot implicitly convert type 'AnonymousType#1[]' to 'AnonymousType#2[]'
. Shouldn't ?:
be able to decide the type since i already have provided the blueprint for the anonymous as var data = new[] { new { Text = "Unknown option", Value = -1 } };
.
Solution:
@Darin Dimitrov answer is great but i want to have some test with anonymous types (Simple cases always need it).
As @Douglas suspects : My assetSequenceRepository
is supplying id
as long
and anonymous Value
goes in favor of int
not long
. since C# compiler does not implicitly cast long
to int
, i got the error. Compiling snippet is:
public JsonResult ChangeFilterList(int option = 3)
{
var data = new[] { new { Text = "Unknown option", Value = long.MaxValue } };
switch (option)
{
case 2: data = _departmentnameRepository.All.Select(x => new { Text = x.DeptName, Value = (long)x.Id }).ToArray();
break;
case 3: data = Session["projectid"] == null
? _assetSequenceRepository.All.Select(x => new { Text = x.AssetShotName, Value = x.Id }).ToArray()
: _assetSequenceRepository.FindBy(p => p.ProjectId == (int)Session["projectid"]).Select(x => new { Text = x.AssetShotName, Value = x.Id }).ToArray();
break;
default: data = _userRepository.All.Select(x => new { Text = x.DisplayName, Value = (long)x.UserID }).ToArray();
break;
}
return Json(data, JsonRequestBehavior.AllowGet);
}
My guess is that your FindBy
method returns objects whose properties have different types from the ones you're expecting (e.g. int?
instead of int
). Try specifying a type cast to ensure that your anonymous type has the correct definition:
case 3: data = Session["projectid"] == null
? _assetSequenceRepository.All.Select(x => new { Text = x.AssetShotName, Value = x.Id }).ToArray()
: _assetSequenceRepository.FindBy(p => p.ProjectId == (int)Session["projectid"]).Select(x => new { Text = (string)x.AssetShotName, Value = (int)x.Id }).ToArray();
break;
The key change is:
new { Text = (string)x.AssetShotName, Value = (int)x.Id })
↖ explicit type casts ↗
You are putting the compiler to a real test here. Just write a view model to end its suffering and make things more explicit:
public class MyViewModel
{
public int Value { get; set; }
public string Text { get; set; }
}
and then project your LINQ queries to this view model to avoid any possible ambiguity that might arise from the use of the conditional operator and anonymous types:
public ActionResult ChangeFilterList(int option)
{
var data = new[]
{
new MyViewModel { Text = "Unknown option", Value = -1 }
};
switch (option)
{
case 2: data = _departmentnameRepository
.All
.Select(x => new MyViewModel { Text = x.DeptName, Value = x.Id })
.ToArray();
break;
case 3: data = Session["projectid"] == null
? _assetSequenceRepository
.All
.Select(x => new MyViewModel { Text = x.AssetShotName, Value = x.Id })
.ToArray()
: _assetSequenceRepository
.FindBy(p => p.ProjectId == (int)Session["projectid"])
.Select(x => new MyViewModel { Text = x.AssetShotName, Value = x.Id })
.ToArray();
break;
default: data = _userRepository
.All
.Select(x => new MyViewModel { Text = x.DisplayName, Value = x.UserID })
.ToArray();
break;
}
return Json(data, JsonRequestBehavior.AllowGet);
}