AutoMapper, InvalidCastException: Unable to cast object of type 'System.Collections.Generic.List`1[System.Byte]' to type 'Google.Protobuf.ByteString' - protocol-buffers

I am new to AutoMapper.
I am retrieving Ink Strokes from a database as a byte[] and then trying to serialize these to a Google.ProtoBuf.ByteString.
I consistently get the Error:
InvalidCastException: Unable to cast object of type
'System.Collections.Generic.List`1[System.Byte]' to type
'Google.Protobuf.ByteString'.
Here is what I have:
In the Protobuf file:
message LoadInkResponse {
bytes Strokes =1;
}
In my domain model:
public class LoadInkResponse
{
public byte[] Strokes { get; set; }
}
And, lastly, in the AutoMapperProfile.cs ,
CreateMap<Model.Models.ProgressNotesModel.LoadInkResponse, LoadInkResponse>()
.ForMember(dest => dest.Strokes, opt => opt.MapFrom(src => ByteString.CopyFrom(src.Strokes)));
where ByteString.CopyFrom is from the Google.Protobuf assembly.
All my attempts at converting the domain byte[] to the DTO ByteString have failed with the same error message.
How is this done????
TIA.

For anyone getting here, #Lucian Bargaoanu, is correct. All my attempts at using a "ForMember" value resolver failed.
However, creating this simple type converter works.
public class ByteStringTypeConverter : ITypeConverter<byte[], ByteString>
{
public ByteString Convert(byte[] source, ByteString destination, ResolutionContext context)
{
return ByteString.CopyFrom(source);
}
}
CreateMap<byte[], ByteString>().ConvertUsing(new ByteStringTypeConverter());
CreateMap<Model.Models.ProgressNotesModel.LoadInkResponse, LoadInkResponse>();

Related

unable to query child properties in OData with Web Api

I am using odata and attempting to filter queries on the properties of a child class.
I am using MongoDb to store a series of object and am wanting to query these objects using OData. The objects are auto generated from xml so there is some annoying inheritance, the basic object scenario is below.
public class Container {
public Parent Property {get; set;}
}
public class Parent {}
public class Child : Parent {
public StringWrapper Value {get; set;}
}
public class StringWrapper {
public string Value {get; set;}
}
So I have made the Container into an entity and made a controller which has the code:
public ContainerController : ODataController {
public PageResult<Container> Get(ODataQueryOptions<Container> queryOptions) {
IQueryable<Container> containers = mongoRepo.All();
var filteredContainers = queryOptions.ApplyTo(containers)
as IQueryable<Container>;
return new PageResult<Container>(filteredContainers,
Request.GetNextPageLink(),
Request.GetInlineCount());
}
}
I am then querying this with the uri:
http://...Container?$filter=Property/NS.Child/Value/Value eq 'example'
If I throw a break point after applying the queryoptions and look at the IQueryable.Expression it gives the result:
value(MongoDB.Driver.Linq.MongoQueryable`1[NS.Container])
.Where($it => (IIF((IIF((($it.Property As Child) == null), null, ($it.Property As Child).Value) == null), null, ($it.Property As Child).Value.Value) == value(System.Web.Http.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.String]).TypedProperty))
when this is then resolved I get the following error
Unable to determine the serialization information for the expression: .
Edit
I tried implementing this basic case without using the mongo db and the same query works fine. I then tried a test with the mongo C# driver for using .where with the As method this resulted in the same error.
I found the query
queryable.Where(
it => (it.Property is Child && ((Child)it.Properties).Value.Value == "example"));
works correctly and was wondering if there is a way to get the query into this form from the same uri or alternatively get the C# driver for mongodb to convert as queries into this form?
Can you try this instead,
var filteredContainers = queryOptions.ApplyTo(containers,
new ODataQuerySettings
{
EnableConstantParameterization = false,
HandleNullPropagation = HandleNullPropagationOption.False
});
?

How to Parse Json webService response in WP7

I want to display data in Listbox without using any DLL.And my webservice responding in json format.
My Web service Response is as below.it has more than 800 records
[
{
"st_id":"1",
"st_name":"name xyz"
},
{
"st_id":"2",
"st_name":"name ABC"
},
{
"st_id":"3",
"st_name":"name HIJK"
},
{
"st_id":"4",
"st_name":"name OPQ"
},
]
my Class for the data is as below
[DataContract]
public class Student
{
[DataMember=("st_id")]
public bool st_id { get; set; }
[DataMember=("st_name")]
public string st_name { get; set; }
}
i m trying serialize object using DataContractJsonSerializer & m getting WS response in Stream.But i am not able to serialize.Suggest links or basic tutorial for Serilize and Deserilize of the json
DataContractJsonSerializer stdserialize =
new DataContractJsonSerializer(typeof(Student));
Student stuser = (Student)stdserialize.ReadObject(responseStream);
so please help for the json response parsing & suggest link for datacontract and all which gives knowledge from basics.
Thanks,
You declared st_id as a bool, but the type of data you're trying to deserialize is string (which can be converted to numbers - not to booleans). Try declaring it as string and it should work.
Also, the response is an array of objects, so the type you should use is Student[]:
DataContractJsonSerializer stdserialize =
new DataContractJsonSerializer(typeof(Student[]));
Student stuser = (Student[])stdserialize.ReadObject(responseStream);

Do i need to create automapper createmap both ways?

This might be a stupid question! (n00b to AutoMapper and time-short!)
I want to use AutoMapper to map from EF4 entities to ViewModel classes.
1) If I call
CreateMap<ModelClass, ViewModelClass>()
then do I also need to call
CreateMap<ViewModelClass, ModelClass>()
to perform the reverse?
2) If two classes have the same property names, then do I need a CreateMap statement at all, or is this just for "specific/custom" mappings?
For the info of the people who stumble upon this question. There appears to be now a built-in way to achieve a reverse mapping by adding a .ReverseMap() call at the end of your CreateMap() configuration chain.
In AutoMapper you have a Source type and a Destination type. So you will be able to map between this Source type and Destination type only if you have a corresponding CreateMap. So to answer your questions:
You don't need to define the reverse mapping. You have to do it only if you intend to map back.
Yes, you need to call CreateMap to indicate that those types are mappable otherwise an exception will be thrown when you call Map<TSource, TDest> telling you that a mapping doesn't exist between the source and destination type.
I've used an extension method do mapping both ways
public static IMappingExpression<TDestination, TSource> BothWays<TSource, TDestination>
(this IMappingExpression<TSource, TDestination> mappingExpression)
{
return Mapper.CreateMap<TDestination, TSource>();
}
usage:
CreateMap<Source, Dest>().BothWays();
Yes, or you can call CreateMap<ModelClass, ViewModelClass>().ReverseMap().
If two classes have same Member(Property,Field,GetMethod()), you needn't call CreateMap<TSrc,TDest>. Actually, if every member in TDest are all exist in TSrc, you needn't call CreateMap<TSrc,TDest>. The following code works.
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
class Person2
{
public string Name { get; set; }
public int? Age { get; set; }
public DateTime BirthTime { get; set; }
}
public class NormalProfile : Profile
{
public NormalProfile()
{
//CreateMap<Person2, Person>();//
}
}
var cfg = new MapperConfiguration(c =>
{
c.AddProfile<NormalProfile>();
});
//cfg.AssertConfigurationIsValid();
var mapper = cfg.CreateMapper();
var s3 = mapper.Map<Person>(new Person2 { Name = "Person2" });

How does Protobuf-net support for Dictionary/KeyValuePair works?

I am trying to understand protobuf-net's Dictionary/KeyValuePair support. We would like to use the underlying binary stream and the generated proto file from java, but the generated .proto file contains what look like a custom type called Pair_String_Int32.
Can someone please shed some light on this?
I've got a class mapped like this:
[DataContract]
public class ForwardCurve
{
[DataMember(Order=1, IsRequired = true)]
public string Commodity { get; set; }
[DataMember(Order = 2, IsRequired = false)]
public IDictionary<string, int> DictValue { get; set; }
[DataMember(Order = 3, IsRequired = false)]
public IList<string> ListValue { get; set; }
}
The generated .proto file using Serializer.GetProto will be:
message ForwardCurve {
required string Commodity = 1;
repeated Pair_String_Int32 DictValue = 2;
repeated string ListValue = 3;
}
So what is Pair_String_Int32 (and what is going into the protobuffer byte stream) and is there any way of mapping this so that protobuf, by using protoc can create the equivalent mapping code in Java?
To get this for work add a new message to the generated .proto file that looks like this.
message Pair_String_Int32 {
required string Key = 1;
required int32 Value = 2;
}
Then protoc will be able to create the corresponding code for Java.
I can check later (I'm on iPod at the moment) but I believe is it simply a "repeated" set of a dummy type with members key=1 value=2 (using the default types for each - so c# string maps to proto string etc). I am in the process of re-implementing GetProto for v2, so I'll try to ensure these dummy types are included in the output.

InsertOnSubmit with interfaces (LINQ to SQL)

In our code we have:
public interface ILogMagazine
{
string Text { get; set; }
DateTime DateAndTime { get; set; }
string DetailMessage { get; set; }
}
SimpleDataContext: DataContext
{
public Table<ILogMagazine> LogMagaines
{
get { return GetTable<ILogMagazine>(); }
}
}
We try to:
DataContext db = new SimpleDataContext("...");
ILogMagazine lg = new LogMagazine()
{
Text = "test",
DateAndTime = DateTime.Now,
DetailMessage = "test",
};
db.LogMagazines.InsertOnSubmit(lg); // Exception thrown
db.SubmitChanges();
Exception: System.InvalidOperationException: The type 'DataLayer.ILogMagazine' is not mapped as a Table..
How we can solve this problem?
The error is because you haven't applied the [Table] attribute (normally it'd go on a class type, in your case the interface type), but I don't see it working even if you did. That's how the mapping is done- when you call GetTable, it looks for the Table attribute to know where to insert/query the data from.
That said, I'm pretty sure you can't do this with an interface. The type on GetTable has to be concrete, because it uses the generic arg passed (or inferred) on GetTable to know what object to create for a query. While it might technically be able to work for inserts, the same GetTable is used for both inserts and queries- which it most certainly won't work for. Same reason XmlSerializer and DataContractSerializer don't work with interfaces.
You'll always need a concrete type, but your entity types can still implement interfaces. I'm guessing you're trying to shuttle these around somewhere (service layer, perhaps), and you'll probably need to rethink that a bit.

Resources