ASP MVC filling model as List Exception - asp.net-mvc

Im stuck at the follow code:
I have a Model OrderList which contains just the following:
public class OrderList : List<Tuple<Bagel, BagelType, int>>
{
}
And in my controller I want to make a new OrderList en fill it with a function:
public ActionResult OrderReport()
{
OrderList lstitems = FillBagelCart2();
return ViewPdf("Order report", "ReportView",lstitems);
}
FillBagelCart2 returns a List<Typle<Bagel, BagelType, int>>
The error is:
Error 14 Cannot implicitly convert type 'System.Collections.Generic.List>' to 'BestelBagels.Models.OrderList'. An explicit conversion exists (are you missing a cast?)
No idea why this doesn't work..
Greets
Already works! I had to make a function which returns an orderlist, filled up with the values like that list.. Can be closed

Whilst you can implicitly cast from OrderList to List<Tuple<Bagel,BagelType,int>> because it inherits from it you cannot cast in the opposite direction because it would be possible for OrderList to contain methods and properties that the base list doesn't implement.
You either need change the return type of FillBagelCart2 to OrderList or provide the appropriate constructor to your OrderList class to allow it to take an existing collection.
public class OrderList : List<Tuple<Bagel, BagelType, int>>
{
public OrderList() : base() {}
public OrderList(IEnumerable<List<Tuple<Bagel,BagelType,int>> items) : base(items) {}
}
Then you can do
OrderList lstitems = new OrderList(FillBagelCart2());

Related

Cannot use enum in repository query (neo4j/Spring Data)

I'm having a problem querying based on an Enum property of my NodeEntity.
The NodeEntity in question is defined:
#NodeEntity(label = "Entity")
public class MyEntity {
#GraphId
private Long internalId;
....
private State state;
#Transient
public enum State {
STATEONE, STATETWO, STATETHREE
}
....
It saves without a problem, the state Enum represented perfectly, and I can query using other properties (Strings) with no problem at all. However the problem is the following query in a repository:
#Query("MATCH (entity:Entity {state:{0}})" +
"RETURN entity")
List<MyEntity> findByState(MyEntity.State state)
i.e. find all entities with the given state.
There's no exception, however using this simply returns a List of 0 Entities.
I've tried all kinds of variations on this, using a WHERE clause for example, with no luck.
The Entities are persisted properly, using findAll() in the same test returns the expected List of Entities with their states exactly as I would expect.
Any thoughts?
Not quite sure what the value #Transient adds to the enum. It is anyway not persistable as a node or relationship in Neo4j. It is sufficient to define the field as one that should persist with
private State state;
and leave off the #Transient annotation from the enum.
With it, SDN ignores the field sent to the derived query.
However, if you have a good reason to mark the enum #Transient, please do share it and we'll re-visit this case.
There is a general problems using spring data rest interface to search on enum fields. Just using the enum-to-string converter cannot work for search where you want to find if the value is IN a collection of values:
public interface AppointmentRepository extends Neo4jRepository<Appointment, Long> {
Page<Appointment> findByDayOfWeekIn(#Param("days") List<DayOfWeek> days, Pageable pageable);
}
The above does not work out of the box because neo4j will try to convert a List to your property type: DayOfWeek
In order to work around this I needed a custom converter that handles both requests providing collection of values (the search) and single values (the normal read and write entity):
#SuppressWarnings({ "unchecked", "rawtypes" })
public abstract class SearchQueryEnumConverter<T extends Enum> {
private Class<T> enumType;
public SearchQueryEnumConverter() {
enumType = (Class<T>) ((ParameterizedType) this.getClass()).getActualTypeArguments();
}
public Object toGraphProperty(Object value) {
if (Collection.class.isAssignableFrom(value.getClass())) {
List<T> values = (List<T>) value;
return values.stream().map(Enum::name).collect(Collectors.toList());
}
return ((Enum) value).name();
}
public Object toEntityAttribute(Object value) {
if (Collection.class.isAssignableFrom(value.getClass())) {
List<String> values = (List<String>) value;
return values.stream().map(v -> (T) T.valueOf(enumType, v)).collect(Collectors.toList());
}
return (T) T.valueOf(enumType, value.toString());
}
}
The abstract converter can be reified by all enums, and used as parameter of the #Convert annotation:
public enum EnumType {
VALUE_A, VALUE_B;
public static class Converter extends SearchQueryEnumConverter<EnumType> implements AttributeConverter {
}
}
#NodeEntity
public Entity {
#Property
#Convert(EnumType.Converter.class)
EnumType type;
}

How can I use Automapper to map all zero int values to null values for nullable int targets?

I use int? for all my required 'FK' properties in ViewModels. This gives me an easy way of specifying on a Create view model that a value is nullable and must be assigned a value to satisfy the Required attribute.
My problem comes in because I create the domain model entity first, using a domain factory, then map it to the view model. Now, many of the nullable ints in the view model get assigned 0 from non-nullable ints in the domain model. I would prefer not to build the new entity in the view model and only map it back to the domain model to avoid his. What else can I do? i'm sure there is som Automapper voodoo that can help me.
EDIT: you dont need to do any of this, but i thought i'd leave it here for people looking for a similar solution. really all you have to do is just provide a mapping from int to int? like this: Mapper.Map<int, int?>()
in that case, I believe you could use a custom type converter, which inherits from automappers ITypeConverter. This code works, I've run it through .NET Fiddle:
using System;
using AutoMapper;
public class Program
{
public void Main()
{
CreateMappings();
var vm = Mapper.Map<MyThingWithInt, MyThingWithNullInt>(new MyThingWithInt());
if (vm.intProp.HasValue)
{
Console.WriteLine("Value is not NULL!");
}
else
{
Console.WriteLine("Value is NULL!");
}
}
public void CreateMappings()
{
Mapper.CreateMap<int, int?>().ConvertUsing(new ZeroToNullIntTypeConverter ());
Mapper.CreateMap<MyThingWithInt, MyThingWithNullInt>();
}
public class ZeroToNullIntTypeConverter : ITypeConverter<int, int?>
{
public int? Convert(ResolutionContext ctx)
{
if((int)ctx.SourceValue == 0)
{
return null;
}
else
{
return (int)ctx.SourceValue;
}
}
}
public class MyThingWithInt
{
public int intProp = 0;
}
public class MyThingWithNullInt
{
public int? intProp {get;set;}
}
}
You can always use the .ForMember() method on your mapping. Something like this:
Mapper
.CreateMap<Entity, EntityDto>()
.ForMember(
dest => dest.MyNullableIntProperty,
opt => opt.MapFrom(src => 0)
);

ASP.NET MVC 3 views, super classes don't work for subclasses?

I have the following classes -
public abstract class BusinessObject { }
public abstract class Form: BusinessObject { }
public abstract class BillableForm: Form { }
public class MembershipForm: BillableForm { }
public abstract class Dto<T>: where T: BusinessObject { }
public abstract class InboxDto<T>: Dto<T> where T: Form { }
public class MembershipFormDto: InboxDto<MembershipForm> { }
And I have the following views -
membershipform.cshtml:
#model AdminSite.Models.MembershipFormDto
#{
Layout = "~/Views/Inbox/Shared/_LayoutForm.cshtml"
}
_LayoutForm.cshtml:
#model InboxDto<Form>
When I land on the membershipform.cshtml page, I get the following exception stating:
The model item passed into the dictionary is of type 'AdminSite.Models.MembershipFormDto', but this dictionary requires a model item of type 'AdminSite.Infrastructure.Models.InboxDto`1[BusinessLogic.Inbox.Form]'.
From everything I can tell, MembershipFormDto IS-A InboxDto of type MembershipForm, where MembershipForm IS-A Form. What gives?
This turned out to be an issue of covariance.
I added the following interface -
public interface IInboxDto<out T>
and modified the InboxDto class to implement that interface -
public abstract class InboxDto<T>: Dto<T>, IInboxDto<T> where T: Form { }
In short, covariance is going from a more defined type to a less defined type; specifically referencing a more defined object with a less defined reference. The reason the compiler complains is it's preventing a scenario like this:
List<String> instanciatedList = new List<String>;
List<Object> referenceList = instanciatedList;
referenceList.add(DateTime);
The final line makes sense, a DateTime IS-A Object. We've said referenceList is a List of Object. However it's instanciated as a List of String. A List of Object is more permissive than a List of String. Suddenly our guarantees from new List<String> are being ignored.
However the out and in keywords for Interface definitions tells the compiler to relax, we know what we're doing and understand what we're getting ourselves into.
More information.

NoSuchMethodException in Struts2

I have textfield for birthDate. When a user enter invalid date, let say for example a String, error message successfully displayed as fielderror. But in my console, I got this error:
java.lang.NoSuchMethodException: Profile.setBirthDate([Ljava.lang.String;)
Have I missed something that's why I encountered the error?
In your Action class you dont have a method called setBirthDate(String birthDate), add it your issue should be resolved.
Note check to see that you have placed all getter and setter in your action class for all properties.
I think in your JSP you have :
<s:textfield name="birthDate" />
Struts will try to map this to setBirthDate(String string), since this method is missing in your action hence the NoSuchMethodException
Update:
To convert String to Date:
public class MyStringToDateConverter extends StrutsTypeConverter {
public Object convertFromString(Map context, String[] values, Class toClass) {
//Parse String to get a date object
}
public String convertToString(Map context, Object o) {
// Get the string from object o
}
}
If you are using Annotation in your action class then add #Conversion() to your action
#Conversion()
public class MyAction extends ActionSupport{
public Date myDate = null;
#TypeConversion(converter="MyStringToDateConverter") //Fully qualified name so if this class is in mypackage then converter will be "myPackage.MyStringToDateConverter"
public void setMyDate(Date date) {
this.myDate = date;
}
}
If you dont want to use Annotation then you can look at the official documentation for example.

Type cast from Java.Lang.Object to native CLR type in MonoDroid

How to cast Java.Lang.Object to some native type?
Example:
ListView adapter contains instances of native type Message. When i am trying to get SelectedItem from ListView it returns instance of Message type casted to Java.Lang.Object, but I can't find solution to cast Java.Lang.Object back to Message.
var message = (Message)list.SelectedItem;
// throws Error 5 Cannot convert type 'Java.Lang.Object' to 'Message'
Please Help.
After long time debuging, have found the solution:
public static class ObjectTypeHelper
{
public static T Cast<T>(this Java.Lang.Object obj) where T : class
{
var propertyInfo = obj.GetType().GetProperty("Instance");
return propertyInfo == null ? null : propertyInfo.GetValue(obj, null) as T;
}
}
Usage example:
var message = list.GetItemAtPosition(e.Position).Cast<Message>();
bundle.PutInt("Message", message.ID);
After careful sdk study have found MonoDroid integrated extension for this purpose:
public static TResult JavaCast<TResult>(this Android.Runtime.IJavaObject instance)
where TResult : class, Android.Runtime.IJavaObject
Member of Android.Runtime.Extensions
The least magical way of getting a native type from the Spinner is to call
message = ((ArrayAdapter<Message>)list.Adapter).GetItem(list.SelectedItemPosition);
I used this code from above answer and it works fine to me
public static class ObjectTypeHelper
{
public static T Cast<T>(this Java.Lang.Object obj) where T : class
{
var propertyInfo = obj.GetType().GetProperty("Instance");
return propertyInfo == null ? null : propertyInfo.GetValue(obj, null) as T;
}
}
and this is how I used
var selectedLocation = locationSpinner.SelectedItem.Cast<Location>();
I am able to get my location object fine from spinner
For generic collections, the right answer would be to use JavaList, which is a Java.Lang.Object and also implements IList. But it involves more work that's for sure. This is actually just an adapter for Java's ArrayList implementation.
You could always try the JavaCast<> method (most of the views implement this)(not tested):
var message = list.SelectedItem.JavaCast< Message >();
If for some reason GetChildAtPosition is not possible, serialise the object to json string and then deserialise the string back to native class.
All of the above answers are correct but I found the simplest way for my case was to make the object a subclass of Java.Lang.Object.
For example I'm writing a Android app in Monotouch, mimicking the concept of a UITableView in iOS using the ExpandableListAdapter, which requires the equivalent of UITableViewCells, so I subclassed cell objects from Java.Lang.Object allowing me to implement a subclass of ExpandableListAdapter such as
public override Java.Lang.Object GetChild(int position, int childPosition)
Etc.
it's work for me:
public class HolderHelper<T> : Java.Lang.Object {
public readonly T Value;
public HolderHelper (T value)
{
this.Value = value;
}
}
test:
chkFileName.Tag = new HolderHelper<LinkInfo> (item);
LinkInfo link= (chkFileName.Tag as HolderHelper<LinkInfo>).Value;

Resources