Base solution for your next web application
Open Closed

Getting BadRequest for auto-generated service proxies #200


User avatar
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)
  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    Unfortunately, auto generated web api controller actions don't support primitive parameters. Use a DTO instead long. You can use "IdInput<long> input" instead of "long userId". In this case, you should send id instead of userId from javascript.

  • User Avatar
    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.<ReadAsAsyncCore>d__01.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.ModelBinding.FormatterParameterBinding.<ExecuteBindingAsyncCore>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.HttpActionBinding.<ExecuteBindingAsyncCore>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__0.MoveNext() System.OperationCanceledException: The operation was canceled. at System.Threading.CancellationToken.ThrowOperationCanceledException() at System.Net.Http.HttpContentExtensions.<ReadAsAsyncCore>d__01.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.ModelBinding.FormatterParameterBinding.<ExecuteBindingAsyncCore>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.HttpActionBinding.<ExecuteBindingAsyncCore>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__0.MoveNext()

    any ideia?

  • User Avatar
    0
    hikalkan created
    Support Team

    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.

  • User Avatar
    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.&lt;WriteBufferedResponseContentAsync&gt;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.&lt;GetInterceptorDelegate&gt;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&lt;long&gt;
        {
            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&lt;Tenant, User&gt;
        {
            public override string ToString()
            {
                return string.Format("[User {0}] {1}", Id, UserName);
            }
    
            public virtual Profile Profile { get; set; } 
        }
    

    ProfileService Method:

    public Profile GetProfile(IdInput&lt;long&gt; 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();
            }
    
  • User Avatar
    0
    thiago floriano created

    I've figured that out:

    ProfileAppService was returning an Entity so I found this: <a class="postlink" href="http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization#handling_circular_object_references">http://www.asp.net/web-api/overview/for ... references</a>

    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!!!

  • User Avatar
    0
    hikalkan created
    Support Team

    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.