Service Stack Client for 3rd party needs a parameter called Public - rest

I have a requirement to call a 3rd party rest api using service stack and this is working fine.
But one of the rest api's requires a property called "public"
Is there an attribute I can specify to give it another name in the class but use the public name when it calls the service?
so I have this definition in the class
public string public { get; set; }
The error I get is
Member modifier 'public' must precede the member type and name
Thanks

OK I found what I needed.
I tried the Alias attribute from ServiceStack.DataAnotations.Alias but this did nothing and I am not sure what it is for?
I then found that adding a reference to System.Runtime.Serialization was needed and also adorning the class with
[System.Runtime.Serialization.DataContract]
Now each public property needs the following attribute or it will not pass the parameter to the rest server. IN the case of the property called Public it specifies the name in the DataMember attribute constructor.
[System.Runtime.Serialization.DataMember]
Below is an example
[System.Runtime.Serialization.DataContract]
public class RequestVoiceBaseSearch : VoiceBaseBaseClass, IReturn<ResponseVoiceBaseSearch>
{
[System.Runtime.Serialization.DataMember]
public string action { get; set; }
[System.Runtime.Serialization.DataMember]
public string terms { get; set; }
[System.Runtime.Serialization.DataMember]
public string from { get; set; }
[System.Runtime.Serialization.DataMember]
public string to { get; set; }
[System.Runtime.Serialization.DataMember(Name = "Public")]
public bool _public { get; set; }
[System.Runtime.Serialization.DataMember]
public string rank { get; set; }
public RequestVoiceBaseSearch()
: base()
{
this.action = "Search";
this.terms = "";
}
}
Chris

Related

Using OData with model inheritance cause missing property error

I got this error in my OData with asp.net core implementation during the runtime :The EDM instance of type '[XXX.Asset Nullable=True]' is missing the property 'externalId'.
The problem appear when I try to access the odata endpoint with the expand query: "/odata/v1/precinct?$expand=assets". It seems happening because I put the "ExternalId" property in my base class, its not happening if I put that property in the "Asset".
Below is my recent codes:
public abstract class Entity
{
public int Id { get; set; }
public string ExternalId { get; set; }
}
public class Precinct : Entity
{
public string Name { get; set; }
public string Description { get; set; }
public virtual IEnumerable<Asset> Assets { get; set; }
}
public class Asset : Entity
{
public string Name { get; set; }
public string Description { get; set; }
}
and here is my model configuration for ODATA
public class AssetModelConfiguration : IModelConfiguration
{
public void Apply(ODataModelBuilder builder, ApiVersion apiVersion)
{
var org = builder.EntitySet<Asset>("asset").EntityType;
org.HasKey(x => x.ExternalId);
org.Ignore(x => x.Id);
}
}
The strange thing is if I put that ExternalId in "Asset" class, it is working. Id property is the primary key while the "ExternalId" is marked as AlternateKey in the DBModel configuration.
am I missing something in my odata configuration? already tried many things but couldn't find a good answer. Any help would be appreciated!

Entity Framework Core 2.0 - Error Migration "Field of entity type is readonly and so cannot be set"

There might be something wrong in my model that I cannot figure out since I get the following error when trying to make a migration:
"An error occurred while calling method 'BuildWebHost' on class Program. Continuing without the application service provider. Error: Field 'k__BackingField' of entity type 'MapeoArticuloProveedor' is readonly and so cannot be set.
Unable to create an object of type 'NSideoContext'. Add an implementation of 'IDesignTimeDbContextFactory' to the project, or see https://go.microsoft.com/fwlink/?linkid=851728 for additional patterns supported at design time."
Entities:
[Table("MapeosArticuloProveedor", Schema = "public")]
public class MapeoArticuloProveedor
{
public string Codigo { get; set; }
public int? IdLadoDeMontaje { get; set; }
[ForeignKey("IdLadoDeMontaje")]
public virtual LadoDeMontajeMapeoArticulo LadoDeMontaje { get; }
}
[Table("LadosDeMontajeMapeosArticulos", Schema = "public")]
public class LadoDeMontajeMapeoArticulo
{
public string Codigo { get; set; }
public string Valor { get; set; }
}
What could it be?
#WanneBDeveloper basically you're exposing the property since you made it public. A more conservative approach would be to set it as follows:
public LadoDeMontajeMapeoArticulo LadoDeMontaje { get; private set; }
note the private keyword
Then the propery can only be set from within the class and not outside of it. Therefore you'll know which class is mutating it's state.
this is your issue:
public virtual LadoDeMontajeMapeoArticulo LadoDeMontaje { get; }
Basically the error is saying you can't set the "LadoDeMontaje" once it is retrieved.
Simply change it to:
public virtual LadoDeMontajeMapeoArticulo LadoDeMontaje { get; set; }

Passing Generic Class' Property to ColumnAttribute in Code First Migration

I have an abstract class inherited in 3 POCO objects:
public abstract class BaseObject
{
public virtual int Id { get; set; }
}
public class Post : BaseObject
{
public string Name { get; set; }
public virtual ICollection<PostCategory> PostCategory { get; set; }
}
public class Category : BaseObject
{
public string Name { get; set; }
public virtual ICollection<PostCategory> PostCategory { get; set; }
}
public class PostCategory
{
[Key]
[Column("Id", Order = 0)]
public int PostId { get; set; }
[Key]
[Column("Id", Order = 1)]
public int CategoryId { get; set; }
public string Value { get; set; }
public virtual Post Post { get; set; }
public virtual Category Category { get; set; }
}
However, whenever I do 'add-migration' in Package Manager Console, I get error:
Schema specified is not valid. Errors: (30,6) : error 0019: Each
property name in a type must be unique. Property name 'Id' was already
defined.
Basically complaining the ColumnAttribute having same property name (Id property in PostCategory object).
I need the property name to be the same for creating generic class that is used in generic Repo class. That's why I have the Id in an abstract class. But, this gives me error on CF migration part. Is there a way to get around this?
Thanks!
The ColumnAttribute attribute, sets the name generated in the SQL server. Obviously the column Id cannot be generated twice.
Simply remove the ColumnAttributes, allowing the server to generate the PostCategory table peacefully.

Update Model From Database (Database First)

I'm using MVC3 VS2010 with EF4.1, I have created my DB using SQL Server and I import it to the MVC3 Web Application.
I have a challenge here, when I come to Update Model from Database I do lost all my models files modifications, for example if I'm using attributes in some models for validation or so all that is overwritten with the new model properties.
Is there anyway to Update Model from Database without losing models' information?
OR
where should I define validation on my models instead of using the models' files directly?
Update: As this is still relatively popular, I have created a blog post on this.
http://jnye.co/Posts/19/adding-validation-to-models-created-by-entity-framework-database-first-c
If you want to validate your models, and not use viewModels, use partial classes to define validation attributes. For example:
Say you have a model like
public class User {
public string Name { get; set; }
}
If you wanted to put a string length validator on it you would need to create a partial class and utilise the MetadataTypeAttribute (this lives in System.ComponentModel.DataAnnotations)
The following classes should be defined in their own separate file, NOT put in the same file as your auto generated models.
[MetadataTypeAttribute(typeof(UserMetadata))]
public partial class User {
}
You then define your validation in the UserMetadata class as follows
public class UserMetadata{
[StringLength(50)]
public string Name {get; set;}
}
EDIT
I just found this article which explains the solution in a little more detail
http://themonitoringguy.com/tips-tricks/validating-microsoft-entity-framework-objects-c-mvc/
No, the files will be regenerated every time.
All the classes are defined as partial so you can easily add DataAnnotations using the MetadataTypeAttribute.
Let's say you have a User class defined as follow:
public partial class User {
public string Name {get;set;}
}
Create a IUser interface
public interface IUser {
[Required]
[DisplayName("User name")]
string Name {get;set;}
}
And then extend the User class to specify that IUser will be used as metadata.
[MetadataType(typeof(IUser))]
public partial class User {} //Empty class body
The first rule of any designer is: It it generates any code you can't modify it because it will be completely deleted next time you update anything in the designer.
All generated classes are partial so you can create your own partial part and put your custom logic there. You obviously can't add attributes to properties defined in auto generated part. In case of data annotations it is possible either through buddy classes or by custom T4 template which will contain your own logic to decide which data annotation should be added during code generation. Both scenarios are mostly considered as a bad practice because you should have separate view model per view with validation needed exactly for that view.
Check the namespace of the MainClass is same as Partial, and have the same Attributes. That is my solution.
example:
Metadata: Create this everywhere u want
public class FormMetadata
{
public int Id { get; set; }
public string Description { get; set; }
public Nullable<bool> IsEnable { get; set; }
public Nullable<System.DateTime> CreationDate { get; set; }
public int CompanieId { get; set; }
public string RegularExpression { get; set; }
public virtual ICollection<Field> Fields { get; set; }
[JsonIgnore]
public virtual Company Company { get; set; }
}
MainClass
namespace Transactions.Model
{
public partial class Form
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Form()
{
this.Fields = new HashSet<Field>();
}
public int Id { get; set; }
public string Description { get; set; }
public Nullable<bool> IsEnable { get; set; }
public Nullable<System.DateTime> CreationDate { get; set; }
public int CompanieId { get; set; }
public string RegularExpression { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Field> Fields { get; set; }
public virtual Company Company { get; set; }
}
}
Partial To Use the MetadataType
namespace Transactions.Model
{
[MetadataTypeAttribute(typeof(FormMetadata))]
public partial class Form
{
}
}
If you have problems to Create a Class Partial in the same NameSpace? Don't worry:
Create a Folder
Create the Class Partial in this folder
Change Namespace at the same of MainClass

EF4 - custom ObjectContext and inheritance question

Spinning further on the previous question I had. Let's say I inherit BlogEntry and Comment from Post. I now want to customize them a bit. A comment to a blog post does not need a title but a comment needs a user reference so I move these two fields out from Post and into Comment and Blog entry like this:
public abstract class Post
{
public virtual int Id { get; set; }
public virtual string Text { get; set; }
public virtual DateTime CreatedAt { get; set; }
}
public class BlogEntry : Post
{
public virtual string Header { get; set; }
public virtual Blog Blog { get; set; }
public virtual IEnumerable<Comment> Comments { get; set; }
}
public class Comment : Post
{
public virtual string Header { get; set; }
public virtual int UserId { get; set; }
public virtual BlogEntry BlogEntry { get; set; }
}
Now I create my custom object context:
public class EntityContext : System.Data.Objects.ObjectContext
{
public EntityContext() : base("name=Entities", "Entities")
{
this.Blogs = CreateObjectSet<Blog>();
this.Posts = CreateObjectSet<Post>();
this.Entries = CreateObjectSet<BlogEntry>();
this.Comments = CreateObjectSet<Comment>();
}
public ObjectSet<Blog> Blogs { get; set; }
public ObjectSet<Post> Posts { get; set; }
public ObjectSet<BlogEntry> Entries { get; set; }
public ObjectSet<Comment> Comments { get; set; }
}
This gives me the following actually quite descriptive error message:
Test method threw exception:
System.ArgumentException: There are
no EntitySets defined for the
specified entity type 'BlogEntry'. If
'BlogEntry' is a derived type, use the
base type instead. For example, you
would see this error if you called
CreateObjectSet()
and DiscontinuedProduct is a known
entity type but is not directly mapped
to an EntitySet. The
DiscontinuedProduct type may be a
derived type where the parent type is
mapped to the EntitySet or the
DiscontinuedProduct type might not be
mapped to an EntitySet at all.
Parameter name: TEntity
Now I am not a master of inheritance and stuff but the way I see this would be to add a set of Entries and Comments as ObjectSet< Post> that would solve my problems?
If you create an ObjectSet for a base type (i.e. Post) you can't create one for derived types too, because you can retrieve instances of all types in the inheritance hierarchy from that one ObjectSet.
i.e. ctx.Posts.OfType<BlogEntry>() would return BlogEntry(s).
So the answer is to simply remove the other two sets.
If yo need to do an add for example you can do this:
ctx.Posts.AddObject(new BlogEntry {....});
no problem at all.
To help you write queries more easily you could probably add a couple of properties to your ObjectContext that look like this:
public ObjectQuery<BlogEntity> Blogs{
get{
return ctx.Posts.OfType<BlogEntry>() as ObjectQuery<BlogEntry>;
}
}
and the same for comments.
Hope this helps
Alex