I have a generic response object. This object accepts a type (this will be either an object or a generic list) and contains a generic object and some error information:
[DataContract]
public class Response<T>
{
[DataMember]
public T ReturnObject { get; set; }
[DataMember]
public string ErrorMessage { get; set; }
[DataMember]
public string StackTrace { get; set; }
public void SetErrorInformation(string message, string stackTrace)
{
ErrorMessage = message;
StackTrace = stackTrace;
}
}
I an attempting to pass this object with the needed information through a WCF service. This works fine until I pass a list as the type. The web reference turns the list into an array so when I attempt to use it as a list it cannot convert types. Is there a way to prevent this from happening? Can I get around this?
When you add the reference to your service in visual studio, click on the advanced button on the add service dialog. Here you can change collection type from array to list.
Related
I am running into an issue while looking at SS.
I am writing a custom Stripe implementation and got stuck on web hooks, this in particular:
https://stripe.com/docs/api#event_object
data->object - this can be anything.
Here is my DTO for it:
public class StripeEvent
{
public string id { get; set; }
public StripeEventData data { get; set; }
public string type { get; set; }
}
[DataContract]
public class StripeEventData
{
[DataMember(Name = "object")]
public object _object { get; set; }
}
My hope is to basically just get that object as a string, and then parse it:
var invoice = (StripeInvoice)JsonSerializer.DeserializeFromString<StripeInvoice>(request.data._object.ToString());
Unfortunately the data that is returned from ToString does not have quotes surrounding each json property's name:
Capture
So, the DeserializeFromString returns an object that has everything nulled out.
Why does SS internally strip the quotes out? Is this the proper way to handle a json member that can be one of many different types? I did try the dynamic stuff, but did not have any luck with that either - basically the same result with missing quotes.
I searched very thoroughly for the use of objects and dynamic within DTOs, but there really was nothing that helped with this question.
Thank you!
The issue is that you should never have an object type in DTOs as the serializer has no idea what concrete type to deserialize back into.
The Stripe documentation says object is a hash which you should be able to use a Dictionary to capture, e.g:
public class StripeEventData
{
public Dictionary<string,string> #object { get; set; }
}
Or as an alternative you could use JsonObject which provides a flexible API to access dynamic data.
This will work for flat object structures, but for complex nested object structures you'll need to create Custom Typed DTOs, e.g:
public class StripeEventInvoice
{
public string id { get; set; }
public StripeEventDataInvoice data { get; set; }
public string type { get; set; }
}
public class StripeEventData
{
public StripeInvoice #object { get; set; }
}
I have a few properties that I don't have a direct mapping in the database for, so I'm using the convention of having another variable that is mapped to the database, and a public variable that will be used to do all of my actual work. The common one is [mapping a boolean property to a char column][1], but I also have a StatusID property whose C# enum is different based on the derived type.
My public property has the [NotMapped] attribute on it, and my internal property has the [Column] attribute. I think there's something that because the public property isn't mapped, it's keeping the other property from being mapped as well.
In my project, I start with an abstract base Message class:
[Table("tblMessage")]
public abstract class Message {
[Column("msgIsSample")]
[Required]
internal string dbIsSample { get; set; }
[Column("msgStatusID")]
internal int? dbStatusId { get; set; }
[NotMapped]
public bool IsSample {
get {
return dbIsSample.ToUpper() == "Y";
}
set {
dbIsSample = value ? "Y" : "N";
}
}
public Message() {
this.IsSample = false;
this.dbStatusId = null;
}
}
Right now I only have a single class implementing the base class, Request:
public class Request : Message {
[NotMapped]
public int Status {
get {
return this.dbStatusId.HasValue ? this.dbStatusId.Value : 1;
}
set {
this.dbStatusId = value;
}
}
public Request()
: base() {
this.Status = 1;
}
}
Here is my context:
public class MyContext : DbContext {
public DbSet<Message> Messages { get; set; }
static MyContext() {
Database.SetInitializer<MyContext>(null);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Entity<Message>()
.Map<Request>(m => m.Requires("msgTypeID").HasValue(1));
}
}
Is this something that anyone else has run across? I haven't been able to find anything about why this isn't working, even though this looks like the accepted convention until the EF team adds additional custom mapping. Someone else has to have run across this issue.
When I try to execute this code, I get a DbUpdateException saying that it can't insert a NULL into column "msgIsSample" due to my having set that in the table creation script. This doesn't make any sense because the msgIsSample is defaulted to have a "N".
Instead of making it internal, make it protected internal.
At runtime, EF will subclass your entity dynamically. These extended classes are called dynamic proxies.
EF cannot set your property because it does not have access. To give EF access to your property, it must have either public or protected access. You can still have internal properties, but give subclasses access by adding the protected modifier.
[Table("tblMessage")]
public abstract class Message {
[Column("msgIsSample")]
[Required]
public string dbIsSample { get; protected internal set; }
[Column("msgStatusID")]
public int? dbStatusId { get; protected internal set; }
Does Entity Framework provide an option to retrieve child objects that are only populated with fields that are foreign keys to the parent object?
Sample code might illustrate this better.
Assuming you have the following POCO classes...
public abstract class Base
{
public Guid Id { get; set; }
}
public class User : Base
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Photo : Base
{
public string Description { get; set; }
public User UploadedBy { get; set; }
}
... and assuming you've configured a DbContext correctly, how do you query for a list of all Photos including the UploadedBy object, but where that UploadedBy object only contains the Id property?
I know I can do this...
return await _dbContext.Photos.Include(p => p.UploadedBy).ToListAsync();
... but that returns the entire User object.
I'd like to do something like this...
return await _dbContext.Photos.Include(p => p.UploadedBy.Id).ToListAsync();
... to indicate that I only want the Id property back.
If we could chain those includes we would be able to pick each property on the child object that we want returned.
Or even better, I'd love to be able to configure a setting at a more global level that would make it so that anytime I ask for Photos, give me all members of photos, even child objects, but only populate their foreign keys and nothing more.
The last request is less important though because I could just create the following extension method for each POCO object...
public static IQueryable<Photo> IncludeForigenKeys(this PhotoAlbumDbContext context){
return context.Photos
.Include(photo => photo.UploadedBy.Id);
}
As far as I understand there is no way to partially load a Navigation Property.
However for foreign keys the standard way of accessing these without loading the Nav property is to include the actual key in your model. Eg:
public class Photo : Base
{
public string Description { get; set; }
public int UploadedById { get; set; }
public User UploadedBy { get; set; }
}
This id will be populated even if you don't actually load the whole navigation property.
In the case where you load both you can update either the value on the local or remote end of the nav property and that update will be persisted to the database on save. In my experience EF is very clever around this. The only scenario where it becomes a little more tricky is in unit tests where EF is not maintaining this state.
I just start to learn REST and ServiceStack and there's something about Route that I just can't quite understand. For example if we take the very basic HelloWorld example from GitHub tutorial and re-write it to return collection of User objects. Here is example:
public User
{
public string Name;
public string Address;
public int Age;
}
// Hello - request object without [Route] attribute
public class Hello
{
public string Name { get; set; }
}
public class HelloResponse
{
public IEnumerable<User> Result {get;set;}
}
public class HelloService : Service
{
public object Any(Hello request)
{
return new HelloResponse { // Collection of User object };
}
}
now everything working right and no problems here. But now I want to add another routing url like: /Hello/{name}/Address
Actually this call (GET) to this url will return a single User selected by Age parameter. How I can do this ? Should I add another Service ? And if the url will be:
/Hello/{name}/{age}/Address
It seems I don't understand something.....
See this earlier answer for details about Routing in ServiceStack. The Smart Routing section in ServiceStack's New API explains further options and different precedence.
There are a few problems with your example. First ServiceStack text serializers only support public properties so you need to change your User Model to use public properties instead of fields, e.g:
public User
{
public string Name { get; set; }
public string Address { get; set; }
public int Age { get; set; }
}
Next, Interfaces on DTOs are a bad idea as there's no good reason for it. They're still supported but you can end up with undesirable results. Use a concrete collection like a List<T> which provides more utility, e.g:
public class HelloResponse
{
public List<User> Results { get; set; }
}
Also the routes should match the property names on your DTO exactly, they are case-insensitive when matching against the Request Path, but they need to map to an exact property name, e.g:
/Hello/{Name}/{Age}/Address
I am trying to serialize an object to Azure Mobile Services.
The object contains an array of a second object which should also be serialized.
[DataContract()]
class ObjectA
{
[DataMember(Name= "id")]
public int Id { get; set; }
[DataMember(Name = "info")]
public string info{ get; set; }
[DataMember(Name = "collectionOfB")]
public ObjectB[] myArrayOfB{ get; set; }
}
[DataContract()]
class ObjectB
{
[DataMember(Name= "id")]
public int Id { get; set; }
[DataMember(Name = "info")]
public string info{ get; set; }
}
I have loaded both table's properly and can insert an individual item into each of the tables.
However when I call the InsertAsync method on the table for objectA I receive an error
Cannot serialize member 'myArrayOfB' of type 'namespace.ObjectB[]' declared on type 'ObjectA'
Any idea's on what I need to do to fix this?
Mobile Services doesn't support serialization of arrays. There are two good posts here that show how you might support this:
http://blogs.msdn.com/b/carlosfigueira/archive/2012/08/30/supporting-arbitrary-types-in-azure-mobile-services-managed-client-simple-types.aspx
http://blogs.msdn.com/b/carlosfigueira/archive/2012/09/11/supporting-complex-types-in-azure-mobile-services-clients-implementing-1-n-table-relationships.aspx