Hi all, Can anybody help to solving this problem. I try to add list of UserContacts to the User using repeater. (One to many relation) I get error about Json to Json array deserialization.
Entities;
User
public class User : AbpUser<User>
{
public virtual Guid? ProfilePictureId { get; set; }
...
public virtual ICollection<UserContact> UserContacts { get; set; }
}
UserContacts
[Table("UserContacts")]
public class UserContact : FullAuditedEntity<long>
{
[Required]
public virtual string ContactName { get; set; }
[Required]
public virtual string ContactPhone { get; set; }
public virtual long UserId { get; set; }
public User User { get; set; }
}
DTO
public class UserContactDto : EntityDto<long>
{
public string ContactName { get; set; }
public virtual string ContactPhone { get; set; }
public long UserId { get; set; }
}
UserAppService
public async Task<GetUserForEditOutput> GetUserForEdit(NullableIdDto<long> input)
{
//Getting all available roles
...
var relatedUserContacts = await _userContactRepository.GetAll().Where(c=>c.UserId == input.Id.Value).ToListAsync();
var output = new GetUserForEditOutput
{
Roles = userRoleDtos,
...
RelatedUserContacts = ObjectMapper.Map<List<UserContactDto>>(relatedUserContacts)
};
if (!input.Id.HasValue)
{
...
}
else
{
...
}
return output;
}
CreateOrUpdateUserInput
public class CreateOrUpdateUserInput
{
[Required]
public UserEditDto User { get; set; }
...
public List<UserContactDto> RelatedUserContacts { get; set; }
public CreateOrUpdateUserInput()
{
...
RelatedUserContacts = new List<UserContactDto>();
}
}
GetUserForEditOutput
public class GetUserForEditOutput
{
...
public UserEditDto User { get; set; }
...
public List<UserContactDto> RelatedUserContacts { get; set; }
}
_CreateOrEditModal.cshtml
@model CreateOrEditUserModalViewModel
...
<div id="UserContacts" name="userContacts">
<div class="form-group m-form__group" id="UserContacts">
<label>@L("UserContacts")</label>
<div data-repeater-list="UserContacts" class="col-lg-10">
@foreach (var userContact in Model.RelatedUserContacts)
{
<div data-repeater-item class="form-group m-form__group row align-items-center">
<div class="col-md-4">
<input type="hidden" name="Id" value="@userContact.Id" />
<div class="m-form__group m-form__group--inline">
<div class="m-form__label">
<label>@L("ContactName"):</label>
</div>
<div class="m-form__control">
<input id="ContactName" type="text" name="contactName" value="@userContact.ContactName" class="form-control m-input">
</div>
</div>
<div class="d-md-none m--margin-bottom-10"></div>
</div>
<div class="col-md-4">
<div class="m-form__group m-form__group--inline">
<div class="m-form__label">
<label class="m-label m-label--single">@L("ContactPhone"):</label>
</div>
<div class="m-form__control">
<input id="ContactPhone" type="text" name="contactPhone" value="@userContact.ContactPhone" class="form-control m-input">
</div>
</div>
<div class="d-md-none m--margin-bottom-10"></div>
</div>
<div class="col-md-4">
<div data-repeater-delete="" class="btn-sm btn btn-danger m-btn m-btn--icon m-btn--pill">
<span>
<i class="la la-trash-o"></i>
<span>@L("Delete")</span>
</span>
</div>
</div>
</div>
}
</div>
</div>
<div class="m-form__group form-group row">
<label class="col-lg-2 col-form-label"></label>
<div class="col-lg-4">
<div data-repeater-create="" class="btn btn btn-sm btn-brand m-btn m-btn--icon m-btn--pill m-btn--wide">
<span>
<i class="la la-plus"></i>
<span>Add</span>
</span>
</div>
</div>
</div>
</div>
...
_CreateOrEditModal.js
...
$("#UserContacts").repeater({
initEmpty: false,
show: function () {
$(this).slideDown()
},
hide: function (e) {
$(this).slideUp(e)
}
})
...
this.save = function () {
...
_userService.createOrUpdateUser({
user: user,
assignedRoleNames: assignedRoleNames,
sendActivationEmail: user.SendActivationEmail,
SetRandomPassword: user.SetRandomPassword,
organizationUnits: _organizationTree.getSelectedOrganizations(),
relatedUserContacts: JSON.stringify(user.UserContacts)
}).done(function () {
...
}).always(function () {
...
});
};
Firstly, I know the description a little bit long but I am confused and stuck. Thanks.
4 Answer(s)
-
0
HI @evbenerji, can you share the error stacktrace for JSON serialization as well?
-
0
Mvc.ExceptionHandling.AbpExceptionFilter - Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[Project.Resource.Dtos.UserContactDto]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. Path 'relatedUserContacts.0', line 1, position 667. (relatedUserContacts.0)
-
0
Hi, what is the data type for
user.UserContacts
?It seems that
JSON.stringify(user.UserContacts)
is producing JSON object instead of JSON array -
0
Hi @ryancyq This problem solved when I map the userContacts in _CreateOrEditModal.js like;
this.save = function () { ... var user = $('#UserInformationsForm,#UserDetailsForm').serializeFormToObject(); var userCont = $.map(user.UserContacts, function (el) { return el }); ... _userService.createOrUpdateUser({ user: user, ... relatedUserContacts: userCont }).done(function () { abp.notify.info(app.localize('SavedSuccessfully')); _modalManager.close(); abp.event.trigger('app.createOrEditUserModalSaved'); }).always(function () { ... }); };
Thanks for your suggestions and thanks for your interest.