Base solution for your next web application
Open Closed

Error with HTTP verb on form save for an entity creation #3601


User avatar
0
expertit created

Hello,

I get an error on save for the creation of an entity.

The error is :

{"message":"An error has occurred.","exceptionMessage":"There is an action CreateSubject defined for api controller app/subject but with a different HTTP Verb. Request verb is GET. It should be Post","exceptionType":"System.Web.HttpException","stackTrace":"   at Abp.WebApi.Controllers.Dynamic.Selectors.AbpApiControllerActionSelector.GetActionDescriptorByActionName(HttpControllerContext controllerContext, DynamicApiControllerInfo controllerInfo, String actionName)\r\n   at Abp.WebApi.Controllers.Dynamic.Selectors.AbpApiControllerActionSelector.SelectAction(HttpControllerContext controllerContext)\r\n   at System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)\r\n   at Castle.Proxies.DynamicApiController`1Proxy_4.ExecuteAsync_callback(HttpControllerContext controllerContext, CancellationToken cancellationToken)\r\n   at Castle.Proxies.Invocations.ApiController_ExecuteAsync_4.InvokeMethodOnTarget()\r\n   at Castle.DynamicProxy.AbstractInvocation.Proceed()\r\n   at Abp.WebApi.Controllers.Dynamic.Interceptors.AbpDynamicApiControllerInterceptor`1.Intercept(IInvocation invocation)\r\n   at Castle.DynamicProxy.AbstractInvocation.Proceed()\r\n   at Castle.Proxies.DynamicApiController`1Proxy_4.ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"}

The ISubjectAppService is :

    public interface ISubjectAppService : IApplicationService
    {
        ListResultDto<SubjectsListDto> GetSubjects(GetSubjectsInput input);
        Task CreateSubject(CreateSubjectInput input);

    }

The implementation is :

     public class SubjectAppService : EspertisAppServiceBase, ISubjectAppService
    {
        private readonly IRepository<Subject> _subjectRepository;
        public SubjectAppService(IRepository<Subject> subjectRepository)
        {
            _subjectRepository = subjectRepository;
        }

        public ListResultDto<SubjectsListDto> GetSubjects(GetSubjectsInput input)
        {
            var subjects = _subjectRepository
                .GetAll()
                .WhereIf(
                    !input.Filter.IsNullOrWhiteSpace(),
                    p => p.Name.Contains(input.Filter) ||
                         p.Surname.Contains(input.Filter) ||
                         p.EmailAddress.Contains(input.Filter)
                )
                .OrderBy(p => p.Name)
                .ThenBy(p => p.Surname)
                .ToList();

            return new ListResultDto<SubjectsListDto>(subjects.MapTo<List<SubjectsListDto>>());
        }

        public async Task CreateSubject(CreateSubjectInput input)
        {
            Subject subject = input.MapTo<Subject>();
            await _subjectRepository.InsertAsync(subject);

        }
    }

The js code to save the modal is :

(function($) {
    app.modals.CreateSubjectModal = function () {

        var _modalManager;
        var _subjectService = abp.services.app.subject;
        var _$form = null;

        this.init = function (modalManager) {
            _modalManager = modalManager;
            _$form = _modalManager.getModal().find('form');
            _$form.validate();
        };

        this.save = function () {
            if (!_$form.valid()) {
                return;
            }
            var subject = _$form.serializeFormToObject();
            _modalManager.setBusy(true);
            _subjectService.createSubject(subject).done(function () {
                _modalManager.close();
                location.reload();
            }).always(function () {
                _modalManager.setBusy(false);
            });
        };
    };
})(jQuery);

Thanks for your help,

Best regards,

Albert


6 Answer(s)
  • User Avatar
    0
    alirizaadiyahsi created

    Hi,

    Which browser are you using? Could you clear browser cache and try again?

  • User Avatar
    0
    expertit created

    Hello alirizaadiyahsi,

    I'm using Chrome, I cleared the cache, same result.

    I tried with another browser Firefox, never used with this application and I get the same result.

    I don't understand why the generated abp wep api controller is specifying HTTP Get verb and not POST.

    Best regarsd,

    Albert

  • User Avatar
    0
    alirizaadiyahsi created

    Hi,

    Send your project(<a href="mailto:[email protected]">[email protected]</a>) and then we take a look to understand what is the problem. (Before send, could you remove bin,obj and packages folders to reduce file size)

  • User Avatar
    0
    alirizaadiyahsi created

    Hi,

    I tested your project. I find out there is another problem with your project. Following line is incorrect;

    [AutoMapFrom(typeof(Subject))]
    

    Correct one :

    [AutoMap(typeof(Subject))]
    

    After this change, I didn't get any error while I am creating a "Subject" entity. I could add succesfully.

    Could you try to change auto map config as I mentioned above? And try again?

  • User Avatar
    0
    expertit created

    Hello,

    After making the change, it works.

    Can you explain the difference between attributes,

    AutoMap AutoMapFrom AutoMapTo

    Because in the documentation, the following is used :

    [AutoMapFrom(typeof(Person))] public class PersonListDto : FullAuditedEntityDto { public string Name { get; set; } public string Surname { get; set; } public string EmailAddress { get; set; } }

    This is for List DTO

    and for Input DTO (it's here that I made the mistake)

    [AutoMapTo(typeof(Person))] public class CreatePersonInput { [Required] [MaxLength(Person.MaxNameLength)] public string Name { get; set; } [Required] [MaxLength(Person.MaxSurnameLength)] public string Surname { get; set; } [EmailAddress] [MaxLength(Person.MaxEmailAddressLength)] public string EmailAddress { get; set; } }

    Thanks,

    Best regards,

    Albert

  • User Avatar
    0
    alirizaadiyahsi created

    Hi,

    AutoMap(Object) : two-way mapping AutoMapFrom (Object) : from Object to another mapping AutoMapTo(Object) : to Object from another mapping

    Your mistake: You defined

    [AutoMapFrom(typeof(Subject))]
    

    but you used

    Subject subject = input.MapTo<Subject>();
    

    You want to map from input to entity, but you defined the exact opposite. So you change it to "AutoMap" or "AutoMapTo" is working.