How to return IList<T> - asp.net-mvc

following function return List of records
public IList<T> GetAll()
{
return db.TabMasters.ToList<T>();
}
Error:
'System.Data.Objects.ObjectSet' does not contain a definition for 'ToList' and the best extension method overload 'System.Linq.Enumerable.ToList(System.Collections.Generic.IEnumerable)' has some invalid arguments

I imagine TabMasters is a strongly typed collection and therefore cannot return a list of a generic type. Have you tried db.TabMasters.ToList() instead?

The correct syntax is:
db.TabMasters.Cast<T>().ToList()
Documentation:
IEnumerable<TResult> Enumerable.Cast<TResult>(this IEnumerable source)
List<TSource> Enumerable.ToList<TSource>(this IEnumerable<TSource> source)
If you don't want to use the LINQ extension, List<T> has a public constructor that accepts a single IEnumerable<T> argument

IList<T> is the Interface that is used by List<T> and several other similar containers. You can't return an Interface itself - you have to return an object that implements IList<T>. Though I don't know exactly what your situation is, the best choice is most likely List<T>.
Also, you have a problem with the generic Type T. If you want the method to be generic, then you have to cast all the values in db.TabMasters to Type T. This gets tricky because you'll have to limit the possible Types used for T to prevent Exceptions caused by an invalid cast (see here). If you only need to return one type, then you should define that as the return type instead of using T. For example, lets say that all the values in db.TabMasters are string. Then you'd use:
public IList<string> GetAll()
{
return db.TabMasters.ToList();
}
If you really need the method to be generic, then you have to cast the values in db.TabMasters to the type you want to return:
public IList<T> GetAll<T>()
{
return db.TabMasters.Cast<T>().ToList();
}
Note that if the object type stored in db.TabMasters can't be cast to T, the method will throw an InvalidCastException.
Happy Coding!

have you looked here http://msdn.microsoft.com/en-us/library/dd412719.aspx
there appears to be a couple of methods that may be of use AsEnumerable and GetList seem like possibilities

Related

HTML Helper how to use IEnumerable

I want to create a custom HTML Helper where I can pass a LINQ expression as a parameter, like this:
#Html.GetBackgroundColor(model => model.RiskAssessment)
I want to use it to display some custom css in an MVC view, depending on what the RiskAssessment property is.
So I created a helper method like this:
public static string GetBackgroundColor<T, TResult>(this HtmlHelper<T> htmlHelper, Expression<Func<T, TResult>> expression)
{
...
}
However, that won't compile, the error is IEnumerable does not contain a definition for 'RiskAssessment'
So I changed the method to
public static string GetBackgroundColor<T, TResult>(this HtmlHelper<IEnumerable<T>> htmlHelper, Expression<Func<T, TResult>> expression)
{
...
}
which compiles, so now I presumably have all the objects in the collection but I have no idea how to get the object I want as I can't use use the expression on the IEnumerable, there is no Where() method available. I would have thought I could do something like this:
IEnumerable<T> collection = htmlHelper.ViewData.Model;
T obj = collection.Where(expression)
but I just don't know what I am doing wrong here.
Figured it out, simple mistake. The table header row is set up with #Html.DisplayNameFor(model => modelType), and I was trying to call my custom HTML helper with these parameters. I should have been calling the method on each table row, using #Html.GetBackgroundColor(modelItem => item.RiskAssessment), and this works because I can use htmlHelper.ValueFor(expression) within the method to get the property value.
That said, I have no idea how the header row is generated as Html.DisplayNameFor uses the same method signature as my custom method but Intellisense reports that one of the Expression types is unknown. But that is not an issue for me.
Thanks.

F#, Serialize dynamically generated objects with WebAPI

I am attempting to create Web API controller in F# which returns objects from Entity Framework. SharpObject and SharpContext are my object and DbContext respectively defined in a c# project.
/// Retrieves values.
[<RoutePrefix("api2/values")>]
type ValuesController() =
inherit ApiController()
let values = [| "value1"; "value2" |]
/// Gets all values.
[<Route("")>]
member x.Get() : IEnumerable<SharpObject> =
use context = new SharpContext()
context.SharpObjects.ToList() :> IEnumerable<SharpObject>
Here is SharpObject with the SerializableAttribute.
[Serializable]
public class SharpObject
{
[Key]
public virtual int Id { get; set; }
public virtual string Description { get; set; }
}
The error that I am getting is this:
The type System.Data.Entity.DynamicProxies.SharpObject_3A697B5C46C0BF76858FEAFC93BFED36DD8D4CA2CEACBB178D2D3C38BB2D2052 was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.
When I de-compile this using ILSpy, it looks like this:
[Route("")]
public IEnumerable<SharpObject> Get()
{
SharpContext context = new SharpContext();
IEnumerable<SharpObject> result;
try
{
result = (IEnumerable<SharpObject>)context.SharpObjects.ToList<SharpObject>();
}
finally
{
IDisposable disposable = context as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
return result;
}
What is the best way to get my list to show through in f#?
This happens because the object that you get from EF is not, in fact, of type SharpObject, but rather of that scarily named type, which inherits from SharpObject. This type is called "proxy" and is dynamically generated by EF in order to provide certain services (such as lazy loading, see below).
Because your action is declared as returning IEnumerable<SharpObject>, the default WebAPI's XML serializer expects to find object of that type, and so rightly complains upon finding an object of different type.
One temporary, bandaid-style fix that you can try is to remove the virtual keywords from your entity (why do you have them there, anyway?). It is the presence of the virtual keywords that causes EF to generate the proxy type. Absent virtual, no proxy will be generated, thus making the XML serializer happy.
This, however, will not work once you extend your model to include navigation properties with lazy loading. Those properties, you must make virtual, otherwise lazy loading won't work.
So the correct fix is not to use the same type for both DB-facing DTO and client-facing DTO. Use different types.
Using the same type for these two purposes may seem "convenient" at first, but this road quickly leads to numerous problems. One of small technical problems you have already discovered. But even absent those, conceptually, you almost never, ever want to just serve up your DB records directly to the untrusted user. Some of possible consequences include security holes, badly factored UI code, badly factored database structure, performance problems, and so on.
Bad idea. Don't do it.
P.S. This doesn't actually have anything to do with F#.

About AsEnumerable() behavior

I have an ASP.NET MVC application. Let's suppose that I have this view:
#model IEnumerable<MyClass>
.....
On the server side, I have a linq query, to my database, using EF:
public ActionResult Index()
{
var query = from t in context.MyClass
select t;
//now comes the question
return View(query);
return View(query.AsEnumerable()); //is there any difference?
}
I think that the AsEnumerable() is not necessary because the query will automatically cast to it, so, can someone explain me when the AsEnumerable() is useful?
Thank you!
It is not necessary. The query you have declared results in a sequence, which implements the IEnumerable interface.
As you will see here, the Select extension method of types that implement the IEnumerable, returns a IEnumerable.
public static IEnumerable<TResult> Select<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TResult> selector)
Your query
var query = from t in context.MyClass
select t;
will be compiled to
var query = context.MyClass.Select(x=>x);
hence I am refering to the Select extension method.
Regarding now the use of AsEnumerable()
The AsEnumerable(IEnumerable) method has no effect other than to change the compile-time type of source from a type that implements IEnumerable to IEnumerable itself.
Also
AsEnumerable(IEnumerable) can be used to choose between query implementations when a sequence implements IEnumerable but also has a different set of public query methods available. For example, given a generic class Table that implements IEnumerable and has its own methods such as Where, Select, and SelectMany, a call to Where would invoke the public Where method of Table. A Table type that represents a database table could have a Where method that takes the predicate argument as an expression tree and converts the tree to SQL for remote execution. If remote execution is not desired, for example because the predicate invokes a local method, the AsEnumerable method can be used to hide the custom methods and instead make the standard query operators available.
For further documentation, please have a look here.

TModel not recognized in a Razor Helper as Lamba Expression

I trying to use a Razor Helper that does some if statements for me. I'm passing it a list with certain rules and based on that rule a label and input text field are created.
The problem I have is I can't get it to work with a Lambda expression as parameter. It won't recognize the TModel part.
The helper method is as follows:
#helper CreateCheckbox(Expression<Func<TModel, bool>> expression, object htmlAttributes, List<Rule> ruleList)
{
}
The error I get is: The type of namespace 'TModel' can not be found.
You have to pick a type for TModel. Because your view doesn't have any generic type parameters, there is no way for it to figure out what type it should substitute in for TModel. You have to give it an actual type to work with.
If that's not an option, you might just make an extension method for the HtmlHelper class, and make it a generic method. See this question for an example of how to do that.

Explicit casting doesn't work in default model binding

I am using ASP.NET MVC2 and Entity Framework. I am going to simplify the situation a little; hopefully it will make it clearer, not more confusing!
I have a controller action to create address, and the country is a lookup table (in other words, there is a one-to-many relationship between Country and Address classes). Let's say for clarity that the field in the Address class is called Address.Land. And, for the purposes of the dropdown list, I am getting Country.CountryID and Country.Name.
I am aware of Model vs. Input validation. So, if I call the dropdown field formLand - I can make it work. But if I call the field Land (that is, matching the variable in Address class) - I am getting the following error:
"The parameter conversion from type
'System.String' to type 'App.Country'
failed because no type converter can
convert between these types."
OK, this makes sense. A string (CountryID) comes from the form and the binder doesn't know how to convert it to Country type. So, I wrote the converter:
namespace App {
public partial class Country {
public static explicit operator Country(string countryID) {
AppEntities context = new AppEntities();
Country country = (Country) context.GetObjectByKey(
new EntityKey("AppEntities.Countries", "CountryID", countryID));
return country;
}
}
}
FWIW, I tried both explicit and implicit. I tested it from the controller - Country c = (Country)"fr" - and it works fine. However, it never got invoked when the View is posted. I am getting the same "no type converter" error in the model.
Any ideas how to hint to the model binder that there is a type converter?
Thanks
A type converter is not the same as an explicit or implicit conversion, it's an object that converts values between various types.
I think you need to create a class inherited from TypeConverter that converts between Country and other types, and apply the TypeConverterAttribute to your class to specify the converter to use :
using System.ComponentModel;
public class CountryConverter : TypeConverter
{
// override CanConvertTo, CanConvertFrom, ConvertTo and ConvertFrom
// (not sure about other methods...)
}
[TypeConverter(typeof(CountryConverter))]
public partial class Country
{
...
}

Resources