Search code examples
c#asp.net-mvcazureasp.net-web-apiazure-mobile-services

Can't find a property nameId in Azure mobile services


I am trying to follow this tutorial and create a mobile back-end for a project. I am trying to get all the data in tblField. Here is the error message I get

        {"message":"The query specified in the URI is not valid. Could not find a property named 'Id' on type 
    'cimsmobileService.DataObjects.DTOtblField'.","exceptionMessage":"
Could not find a property named 'Id' on type 
    'cimsmobileService.DataObjects.DTOtblField'.","exceptionType":"Microsoft.Data.OData.ODataException","stackTrace":"   at 
    Microsoft.Data.OData.Query.SyntacticAst.SelectPathSegmentTokenBinder.ConvertNonTypeTokenToSegment(PathSegmentToken tokenIn, IEdmModel model, IEdmEntityType entityType)\r\n   at 
    Microsoft.Data.OData.Query.SyntacticAst.SelectPropertyVisitor.ProcessTokenAsPath(NonSystemToken tokenIn)\r\n   at 
    Microsoft.Data.OData.Query.SyntacticAst.SelectPropertyVisitor.Visit(NonSystemToken tokenIn)\r\n   at 
    Microsoft.Data.OData.Query.SyntacticAst.NonSystemToken.Accept(IPathSegmentTokenVisitor visitor)\r\n   at 
    Microsoft.Data.OData.Query.SyntacticAst.SelectBinder.Bind(SelectToken tokenIn)\r\n   at 
    Microsoft.Data.OData.Query.SelectExpandSemanticBinder.Parse(IEdmEntityType elementType, IEdmEntitySet entitySet, ExpandToken expandToken, SelectToken selectToken, ODataUriParserConfiguration configuration)\r\n   at 
    Microsoft.Data.OData.Query.ODataUriParser.ParseSelectAndExpandImplementation(String select, String expand, IEdmEntityType elementType, IEdmEntitySet entitySet)\r\n   at 
    Microsoft.Data.OData.Query.ODataUriParser.ParseSelectAndExpand(String select, String expand, IEdmEntityType elementType, IEdmEntitySet entitySet)\r\n   at System.Web.Http.OData.Query.SelectExpandQueryOption.get_SelectExpandClause()\r\n   at 
    System.Web.Http.OData.Query.Validators.SelectExpandQueryValidator.Validate(SelectExpandQueryOption selectExpandQueryOption, ODataValidationSettings validationSettings)\r\n   at 
    System.Web.Http.OData.Query.SelectExpandQueryOption.Validate(ODataValidationSettings validationSettings)\r\n   at 
    System.Web.Http.OData.Query.Validators.ODataQueryValidator.Validate(ODataQueryOptions options, ODataValidationSettings validationSettings)\r\n   at 
    System.Web.Http.OData.Query.ODataQueryOptions.Validate(ODataValidationSettings validationSettings)\r\n   at 
    System.Web.Http.OData.EnableQueryAttribute.ValidateQuery(HttpRequestMessage request, ODataQueryOptions queryOptions)\r\n   at
     System.Web.Http.OData.EnableQueryAttribute.ExecuteQuery(Object response, HttpRequestMessage request, HttpActionDescriptor actionDescriptor)\r\n   at 
    System.Web.Http.OData.EnableQueryAttribute.OnActionExecuted(HttpActionExecutedContext actionExecutedContext)"}

In the WebApiConfig class

public static class WebApiConfig
{
    public static void Register()
    {
        // Use this class to set configuration options for your mobile service
        ConfigOptions options = new ConfigOptions();

        // Use this class to set WebAPI configuration options
        HttpConfiguration config = ServiceConfig.Initialize(new ConfigBuilder(options));

        // To display errors in the browser during development, uncomment the following
        // line. Comment it out again when you deploy your service for production use.
        // config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
        
        // Set default and null value handling to "Include" for Json Serializer
        config.Formatters.JsonFormatter.SerializerSettings.DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Include;
        config.Formatters.JsonFormatter.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Include;
        
        Database.SetInitializer(new cimsInitializer());

        Mapper.Initialize(cfg =>
        {
            cfg.CreateMap<DTOtblField, tblField>();
            cfg.CreateMap<tblField, DTOtblField>()
                .ForMember(dst => dst.DTOkeyFieldID, map => map.MapFrom(x => x.Id));                   
        });

    }
}

public class cimsInitializer : ClearDatabaseSchemaIfModelChanges<cimsContext>
{
    protected override void Seed(cimsContext context)
    {
        List<TodoItem> todoItems = new List<TodoItem>
        {
            new TodoItem { Id = Guid.NewGuid().ToString(), Text = "First item", Complete = false },
            new TodoItem { Id = Guid.NewGuid().ToString(), Text = "Second item", Complete = false },
        };

        foreach (TodoItem todoItem in todoItems)
        {
            context.Set<TodoItem>().Add(todoItem);
        }

        base.Seed(context);
    }
}

Whenever I add tblField like this it throws an error map.MapFrom(x => x.tblField.Id));

Error   2   Cannot convert lambda expression to type 'string' because it is not a delegate type C:\CIMSMobileService\cimsService\App_Start\WebApiConfig.cs  37  32  cimsService

DTOtblFieldController.cs

using System.Linq;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.OData;
using Microsoft.WindowsAzure.Mobile.Service;
using cimsService.Models;
using cimsmobileService.DataObjects;

namespace cimsService.Controllers
{
    public class DTOtblFieldController : TableController<DTOtblField>
    {
        protected override void Initialize(HttpControllerContext controllerContext)
        {
            base.Initialize(controllerContext);
            cims_sarm context = new cims_sarm();
            DomainManager = new DTOtblFieldDomainManager(context, Request, Services);
            //DomainManager = new EntityDomainManager<DTOtblField>(context, Request, Services);
        }

        // GET tables/DTOtblField
        public IQueryable<DTOtblField> GetAllDTOtblField()
        {
            return Query(); 
        }

        // GET tables/DTOtblField/48D68C86-6EA6-4C25-AA33-223FC9A27959
        public SingleResult<DTOtblField> GetDTOtblField(string id)
        {
            return Lookup(id);
        }

        // PATCH tables/DTOtblField/48D68C86-6EA6-4C25-AA33-223FC9A27959
        public Task<DTOtblField> PatchDTOtblField(string id, Delta<DTOtblField> patch)
        {
             return UpdateAsync(id, patch);
        }

        // POST tables/DTOtblField
        public async Task<IHttpActionResult> PostDTOtblField(DTOtblField item)
        {
            DTOtblField current = await InsertAsync(item);
            return CreatedAtRoute("Tables", new { id = current.Id }, current);
        }

        // DELETE tables/DTOtblField/48D68C86-6EA6-4C25-AA33-223FC9A27959
        public Task DeleteDTOtblField(string id)
        {
             return DeleteAsync(id);
        }

    }
}

DTOtblField.cs

    using System.ComponentModel.DataAnnotations;
    using Microsoft.WindowsAzure.Mobile.Service;
    //-------------------------------------------------------------------------------------------------------
    // <auto-generated>
    //     This code was generated by EntitiesToDTOs.v3.2 (entitiestodtos.codeplex.com).
    //     Timestamp: 2015/12/16 - 16:33:45
    //
    //     Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
    // </auto-generated>
    //-------------------------------------------------------------------------------------------------------
    using System;
    using System.Collections.Generic;
    using System.Runtime.Serialization;
    using System.Text;
    using System.ComponentModel.DataAnnotations.Schema;
    
    namespace cimsmobileService.DataObjects
    {
        [DataContract()]
        public partial class DTOtblField:EntityData
        {
            [NotMapped]
            public Int32 keyFieldID { get; set; }
            [DataMember()]
            [Required]
            public string DTOkeyFieldID 
            { 
               
                get{
                    return keyFieldID.ToString();
                   }
    
                set{
                    this.keyFieldID = Int32.Parse(DTOkeyFieldID);
                   }
            }
    
            [DataMember()]
            public String FieldText { get; set; }
    
            [DataMember()]
            public String FieldDefaultEntry { get; set; }
    
            [DataMember()]
            public String ParameterDefaultEntry { get; set; }
    
            [DataMember()]
            public String FieldType { get; set; }
    
            [DataMember()]
            public Nullable<Int32> fk_FieldGroupID { get; set; }
    
            [DataMember()]
            public String fillFlag { get; set; }
    
            [DataMember()]
            public Nullable<Boolean> isHidden { get; set; }
    
            [DataMember()]
            public Nullable<Int32> DisplayOrder { get; set; }
    
            [DataMember()]
            public Nullable<Int32> PercentageWidth { get; set; }
    
            [DataMember()]
            public Nullable<DateTime> StartEffDT { get; set; }
    
            [DataMember()]
            public Nullable<DateTime> EndEffDT { get; set; }
    
            [DataMember()]
            public String SecurityLevels { get; set; }
    
            [DataMember()]
            public List<Int32> tblEntries_keyEntryID { get; set; }
    
            [DataMember()]
            public Int32 tblFieldGroup_keyFieldGroupID { get; set; }
    
            [DataMember()]
            public List<Int32> tblFieldDetails_keyFieldDetailID { get; set; }
    
            [DataMember()]
            public List<Int32> tblLink_FieldToAsset_keyLink_FieldToAsset { get; set; }
    
            [DataMember()]
            public List<Int32> tblLink_FieldToConfiguration_keyLink_FieldToConfiguration { get; set; }
    
            [DataMember()]
            public List<Int32> tblLink_FieldToForm_keyLink_FieldToForm { get; set; }
    
            [DataMember()]
            public List<Int32> tblLink_FieldToLocation_keyLink_FieldToLocation { get; set; }
    
            [DataMember()]
            public List<Int32> tblLink_FieldToTemplate_Asset_keyLink_FieldToTemplate_Asset { get; set; }
    
            public DTOtblField()
            {
            }
    
            public DTOtblField(Int32 keyFieldID, String fieldText, String fieldDefaultEntry, String parameterDefaultEntry, String fieldType, Nullable<Int32> fk_FieldGroupID, String fillFlag, Nullable<Boolean> isHidden, Nullable<Int32> displayOrder, Nullable<Int32> percentageWidth, Nullable<DateTime> startEffDT, Nullable<DateTime> endEffDT, String securityLevels, List<Int32> tblEntries_keyEntryID, Int32 tblFieldGroup_keyFieldGroupID, List<Int32> tblFieldDetails_keyFieldDetailID, List<Int32> tblLink_FieldToAsset_keyLink_FieldToAsset, List<Int32> tblLink_FieldToConfiguration_keyLink_FieldToConfiguration, List<Int32> tblLink_FieldToForm_keyLink_FieldToForm, List<Int32> tblLink_FieldToLocation_keyLink_FieldToLocation, List<Int32> tblLink_FieldToTemplate_Asset_keyLink_FieldToTemplate_Asset)
            {
                this.keyFieldID = keyFieldID;
                this.FieldText = fieldText;
                this.FieldDefaultEntry = fieldDefaultEntry;
                this.ParameterDefaultEntry = parameterDefaultEntry;
                this.FieldType = fieldType;
                this.fk_FieldGroupID = fk_FieldGroupID;
                this.fillFlag = fillFlag;
                this.isHidden = isHidden;
                this.DisplayOrder = displayOrder;
                this.PercentageWidth = percentageWidth;
                this.StartEffDT = startEffDT;
                this.EndEffDT = endEffDT;
                this.SecurityLevels = securityLevels;
                this.tblEntries_keyEntryID = tblEntries_keyEntryID;
                this.tblFieldGroup_keyFieldGroupID = tblFieldGroup_keyFieldGroupID;
                this.tblFieldDetails_keyFieldDetailID = tblFieldDetails_keyFieldDetailID;
                this.tblLink_FieldToAsset_keyLink_FieldToAsset = tblLink_FieldToAsset_keyLink_FieldToAsset;
                this.tblLink_FieldToConfiguration_keyLink_FieldToConfiguration = tblLink_FieldToConfiguration_keyLink_FieldToConfiguration;
                this.tblLink_FieldToForm_keyLink_FieldToForm = tblLink_FieldToForm_keyLink_FieldToForm;
                this.tblLink_FieldToLocation_keyLink_FieldToLocation = tblLink_FieldToLocation_keyLink_FieldToLocation;
                this.tblLink_FieldToTemplate_Asset_keyLink_FieldToTemplate_Asset = tblLink_FieldToTemplate_Asset_keyLink_FieldToTemplate_Asset;
            }
        }
    }

cim_sarm.cs

  namespace cimsService.Models
    {
        using System;
        using System.Data.Entity;
        using System.ComponentModel.DataAnnotations.Schema;
        using System.Data.Entity.ModelConfiguration.Conventions;
        using System.Linq;
        using Microsoft.WindowsAzure.Mobile.Service;
        using Microsoft.WindowsAzure.Mobile.Service.Tables;
    
        public partial class cims_sarm : DbContext
        {
            public cims_sarm()
                : base("name=cims_sarm")
            {
                Database.SetInitializer<cims_sarm>(null);
    
            }   
    
            public virtual DbSet<tblField> tblFields { get; set; }   
    
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
            
    
                modelBuilder.Entity<tblField>()
                    .Property(e => e.FieldType)
                    .IsUnicode(false);
    
                modelBuilder.Entity<tblField>()
                    .Property(e => e.fillFlag)
                    .IsFixedLength()
                    .IsUnicode(false);
    
                modelBuilder.Entity<tblField>()
                    .Property(e => e.SecurityLevels)
                    .IsUnicode(false);
    
                modelBuilder.Entity<tblField>()
                    .HasMany(e => e.tblEntries)
                    .WithRequired(e => e.tblField)
                    .HasForeignKey(e => e.fk_FieldID)
                    .WillCascadeOnDelete(false);
    
                modelBuilder.Entity<tblField>()
                    .HasMany(e => e.tblFieldDetails)
                    .WithRequired(e => e.tblField)
                    .HasForeignKey(e => e.fk_FieldID)
                    .WillCascadeOnDelete(false);
    
                modelBuilder.Entity<tblField>()
                    .HasMany(e => e.tblLink_FieldToAsset)
                    .WithRequired(e => e.tblField)
                    .HasForeignKey(e => e.fk_FieldID)
                    .WillCascadeOnDelete(false);
    
                modelBuilder.Entity<tblField>()
                    .HasMany(e => e.tblLink_FieldToConfiguration)
                    .WithRequired(e => e.tblField)
                    .HasForeignKey(e => e.fk_FieldID)
                    .WillCascadeOnDelete(false);
    
                modelBuilder.Entity<tblField>()
                    .HasMany(e => e.tblLink_FieldToForm)
                    .WithRequired(e => e.tblField)
                    .HasForeignKey(e => e.fk_FieldID)
                    .WillCascadeOnDelete(false);
    
                modelBuilder.Entity<tblField>()
                    .HasMany(e => e.tblLink_FieldToLocation)
                    .WithRequired(e => e.tblField)
                    .HasForeignKey(e => e.fk_FieldID)
                    .WillCascadeOnDelete(false);
    
                modelBuilder.Entity<tblField>()
                    .HasMany(e => e.tblLink_FieldToTemplate_Asset)
                    .WithRequired(e => e.tblField)
                    .HasForeignKey(e => e.fk_FieldID)
                    .WillCascadeOnDelete(false);
       
                string schema = ServiceSettingsDictionary.GetSchemaName();
                if (!string.IsNullOrEmpty(schema))
                {
                    modelBuilder.HasDefaultSchema(schema);
                }
    
                modelBuilder.Conventions.Add(
                    new AttributeToColumnAnnotationConvention<TableColumnAttribute, string>(
                        "ServiceTableColumn", (property, attributes) => attributes.Single().ColumnType.ToString()));
        base.OnModelCreating(modelBuilder);
            }
            
        }
    }

tblField.cs

namespace cimsService.Models
{
    using Microsoft.WindowsAzure.Mobile.Service.Tables;
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Data.Entity.Spatial;

    [Table("tblField")]
    public partial class tblField
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public tblField()
        {
            tblEntries = new HashSet<tblEntry>();
            tblFieldDetails = new HashSet<tblFieldDetail>();
            tblLink_FieldToAsset = new HashSet<tblLink_FieldToAsset>();
            tblLink_FieldToConfiguration = new HashSet<tblLink_FieldToConfiguration>();
            tblLink_FieldToForm = new HashSet<tblLink_FieldToForm>();
            tblLink_FieldToLocation = new HashSet<tblLink_FieldToLocation>();
            tblLink_FieldToTemplate_Asset = new HashSet<tblLink_FieldToTemplate_Asset>();
        }

        [Key]
        public int keyFieldID { get; set; }

        [Required]
        public string FieldText { get; set; }

        public string FieldDefaultEntry { get; set; }

        public string ParameterDefaultEntry { get; set; }

        [StringLength(50)]
        public string FieldType { get; set; }

        public int? fk_FieldGroupID { get; set; }

        [StringLength(1)]
        public string fillFlag { get; set; }

        public bool? isHidden { get; set; }

        public int? DisplayOrder { get; set; }

        public int? PercentageWidth { get; set; }

        public DateTime? StartEffDT { get; set; }

        public DateTime? EndEffDT { get; set; }

        [StringLength(50)]
        public string SecurityLevels { get; set; }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<tblEntry> tblEntries { get; set; }

        public virtual tblFieldGroup tblFieldGroup { get; set; }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<tblFieldDetail> tblFieldDetails { get; set; }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<tblLink_FieldToAsset> tblLink_FieldToAsset { get; set; }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<tblLink_FieldToConfiguration> tblLink_FieldToConfiguration { get; set; }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<tblLink_FieldToForm> tblLink_FieldToForm { get; set; }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<tblLink_FieldToLocation> tblLink_FieldToLocation { get; set; }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<tblLink_FieldToTemplate_Asset> tblLink_FieldToTemplate_Asset { get; set; }

        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        [Index]
        [TableColumn(TableColumnType.CreatedAt)]
        public DateTimeOffset? CreatedAt { get; set; }

        [TableColumn(TableColumnType.Deleted)]
        public bool Deleted { get; set; }

        [Index]
        [TableColumn(TableColumnType.Id)]
        [MaxLength(36)]
        public string Id { get; set; }

        [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
        [TableColumn(TableColumnType.UpdatedAt)]
        public DateTimeOffset? UpdatedAt { get; set; }

        [TableColumn(TableColumnType.Version)]
        [Timestamp]
        public byte[] Version { get; set; }

    }
}

Solution

  • As Adrian mentioned, the Id property is required. Looking at your DTOtblField class above, since you're inheriting from EntityData, you don't have to (and shouldn't) explicitly define an Id property, as that is defined in EntityData, but I'm also noticing that your DTO is auto-generated by a tool, so I'm wondering if there's any chance that tooling is re-writing your object when publishing or during some other step.

    Unless the tool is providing a way for you to specify that it should inherit from EntityData, the recommendation I'd make is for you to have a separate file with the following:

    namespace cimsmobileService.DataObjects
    {
    
        public partial class DTOtblField : EntityData
        {
        }
    }
    

    That will ensure your modifications are persisted, even if the DTO is re-generated by the tool.