Open Closed

Getting BadRequest for auto-generated service proxies #200


0
thiago floriano created

I have a page where I load logged user profile so the user can edit it.

I created a profile service: public interface IProfileAppService : IApplicationService { void CreateProfile(Profile input);

    Profile GetProfile(long userId);
}

and I'm trying to call the service using the proxy, this way: abp.ui.setBusy( //Set whole page busy until getTasks complete null, profileService.getProfile({ //Call application service method directly from javascript data: { userId: abp.session.userId } }).success(function (data) { vm.profile = data.profile; }) );

I got the services proxies through /api/AbpServiceProxies/GetAll and I have this for profileService: serviceNamespace.getProfile = function(userId, ajaxParams) { return abp.ajax($.extend({ url: abp.appPath + 'api/services/app/profile/GetProfile', type: 'POST', data: JSON.stringify(userId) }, ajaxParams)); };

Do I need to pass something as ajaxParams?


6 Answer(s)
  • 0
    hikalkan created

    Hi,

    Unfortunately, auto generated web api controller actions don't support primitive parameters. Use a DTO instead long. You can use "IdInput

  • 0
    thiago floriano created

    It worked!! Thanks!

    But now I'm stuck in this error: I debugged the service and the service is called with the correct param. javascript service call gets a 500 error with no additional info. log file gives me this:

    INFO 2015-07-07 00:35:22,345 [76 ] OMC.Users.ProfileAppService - Getting profile for profile id: 30007 ERROR 2015-07-07 00:35:23,893 [70 ] Default - System.OperationCanceledException: The operation was canceled. at System.Threading.CancellationToken.ThrowOperationCanceledException() at System.Net.Http.HttpContentExtensions.

    any ideia?

  • 0
    hikalkan created

    Strange.. I don't know what is the reason of cancelling the operation. If CustomErrors are "On" in web.config, make it "RemoteOnly" when debugging. Then it may send additional info to client. Also, you can share inside of the service method, maybe we can understand it.

  • 0
    thiago floriano created

    I changed to RemoteOnly and now i get this:

    {  
       "message":"An error has occurred.",
       "exceptionMessage":"The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.",
       "exceptionType":"System.InvalidOperationException",
       "stackTrace":null,
       "innerException":{  
          "message":"An error has occurred.",
          "exceptionMessage":"Error getting value from 'User' on 'System.Data.Entity.DynamicProxies.Profile_D7269BB050FF4B5A76425F662A7A6EB079CD3D7DE170C5A9619E49561232515F'.",
          "exceptionType":"Newtonsoft.Json.JsonSerializationException",
          "stackTrace":"   at Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)\r\n   at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)\r\n   at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)\r\n   at System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)\r\n   at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__1b.MoveNext()",
          "innerException":{  
             "message":"An error has occurred.",
             "exceptionMessage":"The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.",
             "exceptionType":"System.ObjectDisposedException",
             "stackTrace":"   at System.Data.Entity.Core.Objects.ObjectContext.get_Connection()\r\n   at System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)\r\n   at System.Data.Entity.Core.Objects.DataClasses.EntityReference`1.Load(MergeOption mergeOption)\r\n   at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.DeferredLoad()\r\n   at System.Data.Entity.Core.Objects.Internal.LazyLoadBehavior.LoadProperty[TItem](TItem propertyValue, String relationshipName, String targetRoleName, Boolean mustBeNull, Object wrapperObject)\r\n   at System.Data.Entity.Core.Objects.Internal.LazyLoadBehavior.<>c__DisplayClass7`2.<GetInterceptorDelegate>b__2(TProxy proxy, TItem item)\r\n   at System.Data.Entity.DynamicProxies.Profile_D7269BB050FF4B5A76425F662A7A6EB079CD3D7DE170C5A9619E49561232515F.get_User()\r\n   at GetUser(Object )\r\n   at Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)"
          }
       }
    }
    

    I separeted User and Profile. Profile class:

    public class Profile : Entity<long>
        {
            public string Telephone { get; set; }
    
            public string CelPhone { get; set; }
    
            public string City { get; set; }
    
            public string Province { get; set; }
    
            public string Country { get; set; }
    
            public string ResumeDir { get; set; }
    
            public virtual DateTime CreationTime { get; set; }
    
            [Required]
            public virtual User User { get; set; }
    
            public Profile()
            {
                CreationTime = DateTime.Now;
            }
        }
    

    User class:

    public class User : AbpUser<Tenant, User>
        {
            public override string ToString()
            {
                return string.Format("[User {0}] {1}", Id, UserName);
            }
    
            public virtual Profile Profile { get; set; } 
        }
    

    ProfileService Method:

    public Profile GetProfile(IdInput<long> input)
            {
                Logger.Info("Getting profile for profile id: " + input.Id);
                try
                {
                   var profile =  _profileRepository.Get(input.Id);
                   return profile;
                    //_mailService.SendContactUsMail(profile);
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("Error trying to get a profile for ID {2}. \nMessage: {0}, \nStacktrace: {1}", ex.Message, ex.StackTrace, input.Id);
                }
    
                return new Profile();
            }
    
  • 0
    thiago floriano created

    I've figured that out:

    ProfileAppService was returning an Entity so I found this: http://www.asp.net/web-api/overview/for ... references

    Then I created a DtoOutput (IOutputDto) and get the service to map from entity to dto.

    OBS: since the IRepository method Get() return proxy entities, we have to use Mapper.DynamicMap(). Otherwise it throws an exception saying that there is no Mapping Configuration.

    Thanks!!!

  • 0
    hikalkan created

    Hi,

    It returns proxy since EF returns proxy. But even it returns a proxy, AutoMapper will map it. Did you define a mapping for it You can use a [AutoMap(typeof(Profile))] for your DTO class.