Solved!
Just use DTOS as per @ismcagdas
[AutoMapFrom(typeof(Product))]
public class ProductListDto : FullAuditedEntityDto
{
public string Name { get; set; }
public string SharepointMapping { get; set; }
public string BrandName { get; set; }
public string BusinessUnitName { get; set; }
}
FYI Fixed with a little hack returning the parent as a string
public ListResultDto<CategoryListDto>GetCategories()
{
var categories = _categoryRepository.GetAll().ToList()
.Select(r => new CategoryListDto
{
Id = r.Id,
Name = r.Name,
SharepointMapping = r.SharepointMapping,
Parent = GetCategoryName(r.ParentId)
});
return new ListResultDto<CategoryListDto>(categories.MapTo<List<CategoryListDto>>()); ;
}
Hi All Thanks for all the help. I think I have got to the bottom of the issue.
I changed the following code to use default verbs.
Configuration.Modules.AbpWebApi().DynamicApiControllerBuilder
.ForAll<IApplicationService>(typeof(BabcockCRMApplicationModule).Assembly, "app")
.WithConventionalVerbs()
.Build();
So now it will use a get and not post.
When I ran the code I got the following error.
"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":"Self referencing loop detected for property 'parent' with type 'Clarity.BabcockCRM.Models.Category'
So in my opinion this is the error that was causing the issue in the first place. Is there any way to solve this?
Hi There
I removed all parameters. I am retrieving all records so dont need any parameters for now. So the GetCategories class doesnt accept any parameters any more and it still does a get.
Same error.
The funny thing is it only returns the error when there is a record with a ParentId ie the Parent Property is not null. Else the call works fine.
Should I decorate the service with httppost annotation.
Full controller
namespace Clarity.BabcockCRM.Web.Areas.Mpa.Controllers
{
[AbpMvcAuthorize(AppPermissions.Pages_Administration_Categories)]
public class CategoriesController : BabcockCRMControllerBase
{
private readonly ICategoryAppService _categoryAppService;
public CategoriesController(ICategoryAppService categoryAppService)
{
_categoryAppService = categoryAppService;
}
public ActionResult Index(GetCategoriesInput input)
{
var output = _categoryAppService.GetCategories(input);
var model = new IndexViewModel(output);
return View(model);
}
public async Task<PartialViewResult> CreateOrEditModal(int? id)
{
var output = await _categoryAppService.GetCategoryForEdit(new NullableIdDto { Id = id });
var viewModel = new CreateOrEditCategoryModalViewModel(output);
return PartialView("_CreateOrEditModal", viewModel);
}
}
}
Full Category App Service. The Javascript calls the app service directly
[AbpAuthorize(AppPermissions.Pages_Administration_Categories)]
public class CategoryAppService : BabcockCRMServiceBase, ICategoryAppService
{
private readonly IRepository<Category> _categoryRepository;
public CategoryAppService(IRepository<Category> categoryRepository)
{
_categoryRepository = categoryRepository;
}
public ListResultDto<CategoryListDto> GetCategories(GetCategoriesInput input)
{
var categories = _categoryRepository
.GetAll()
.WhereIf(
!input.Filter.IsNullOrEmpty(),
p => p.Name.Contains(input.Filter)
)
.OrderBy(p => p.Name)
.ToList();
return new ListResultDto<CategoryListDto>(categories.MapTo<List<CategoryListDto>>());
}
public async Task CreateOrUpdateCategory(CreateOrUpdateCategoryInput input)
{
if (input.Category.Id.HasValue)
{
await UpdateCategoryAsync(input);
}
else
{
await CreateCategoryAsync(input);
}
}
protected virtual async Task UpdateCategoryAsync(CreateOrUpdateCategoryInput input)
{
Debug.Assert(input.Category.Id != null, "input.Category.Id should be set.");
var category = await _categoryRepository.GetAsync(input.Category.Id.Value);
category.Name = input.Category.Name;
category.SharepointMapping = input.Category.SharepointMapping;
category.ParentId = input.Category.ParentId;
await _categoryRepository.UpdateAsync(category);
}
protected virtual async Task CreateCategoryAsync(CreateOrUpdateCategoryInput input)
{
var category = new Category()
{ Name = input.Category.Name,
SharepointMapping = input.Category.SharepointMapping,
ParentId = input.Category.ParentId};
await _categoryRepository.InsertAsync(category);
await CurrentUnitOfWork.SaveChangesAsync(); //It's done to get Id of the role.
}
public async Task CreateCategory(CreateCategoryInput input)
{
var category = input.MapTo<Category>();
await _categoryRepository.InsertAsync(category);
}
public async Task<GetCategoryForEditOutput> GetCategoryForEdit(NullableIdDto input)
{
var categorylist = _categoryRepository.GetAll().ToList();
CategoryEditDto categoryEditDto;
if (input.Id.HasValue) //Editing existing role?
{
var category = await _categoryRepository.GetAsync(input.Id.Value);
categoryEditDto = category.MapTo<CategoryEditDto>();
}
else
{
categoryEditDto = new CategoryEditDto();
}
return new GetCategoryForEditOutput
{
Category = categoryEditDto,
CategoryList = categorylist.MapTo<List<Category>>().OrderBy(p => p.Name).ToList(),
};
}
public async Task DeleteCategory(EntityDto input)
{
var category = await _categoryRepository.GetAsync(input.Id);
await _categoryRepository.DeleteAsync(category);
}
}
Hi There
Please find controller code below. Still getting issues after forcing javascript to force null values.
public ActionResult Index(GetCategoriesInput input)
{
var output = _categoryAppService.GetCategories(input);
var model = new IndexViewModel(output);
return View(model);
}
Thanks for the reply thats what I thought.
I have not created any custom API for this.
Its being called by jTable in javascript.
_$categoriesTable.jtable({
title: app.localize('Categories'),
actions: {
listAction: {
method: _categoryService.getCategories
}
},
I removed all the records with ParentIds and did not get this error. When I added a parentId to one of them I got the error again.
Not sure what is happening
Could it be an issue with jtable when the navigation property is null.
Category.Parent = null
So then category.parent.name will throw an exception error
My controller and AppService returns data correctly.
Here is full javascript
(function () {
$(function () {
var _$categoriesTable = $('#CategoriesTable');
var _categoryService = abp.services.app.category;
var _permissions = {
create: abp.auth.hasPermission('Pages.Administration.Categories'),
edit: abp.auth.hasPermission('Pages.Administration.Categories'),
'delete': abp.auth.hasPermission('Pages.Administration.Categories')
};
var _createOrEditModal = new app.ModalManager({
viewUrl: abp.appPath + 'Mpa/Categories/CreateOrEditModal',
scriptUrl: abp.appPath + 'Areas/Mpa/Views/Categories/_CreateOrEditModal.js',
modalClass: 'CreateOrEditCategoryModal'
});
_$categoriesTable.jtable({
title: app.localize('Categories'),
actions: {
listAction: {
method: _categoryService.getCategories
}
},
fields: {
id: {
key: true,
list: false
},
actions: {
type: 'record-actions',
cssClass: 'btn btn-xs btn-primary blue',
text: '<i class="fa fa-cog"></i> ' + app.localize('Actions') + ' <span class="caret"></span>',
items: [{
text: app.localize('Edit'),
visible: function () {
return _permissions.edit;
},
action: function (data) {
_createOrEditModal.open({ id: data.record.id });
}
}, {
text: app.localize('Delete'),
visible: function (data) {
return !data.record.isStatic && _permissions.delete;
},
action: function (data) {
deleteRole(data.record);
}
}]
},
Name: {
title: app.localize('CategoryName'),
width: '35%',
display: function (data) {
var $span = $('<span></span>');
$span.append(data.record.name + " ");
return $span;
}
},
SharePointMapping: {
title: app.localize('SharePointName'),
width: '35%',
display: function (data) {
var $span = $('<span></span>');
$span.append(data.record.sharepointMapping + " ");
return $span;
}
},
ParentName: {
title: app.localize('ParentName'),
width: '35%',
display: function (data) {
var $span = $('<span></span>');
$span.append(data.record.parent + " ");
return $span;
}
},
}
});
function deleteRole(role) {
abp.message.confirm(
app.localize('RoleDeleteWarningMessage', role.displayName),
function (isConfirmed) {
if (isConfirmed) {
_roleService.deleteRole({
id: role.id
}).done(function () {
getRoles();
abp.notify.success(app.localize('SuccessfullyDeleted'));
});
}
}
);
};
$('#CreateNewCategoryButton').click(function () {
_createOrEditModal.open();
});
$('#RefreshCategoriesButton').click(function (e) {
e.preventDefault();
getCategories();
});
function getCategories() {
_$categoriesTable.jtable('load');
}
abp.event.on('app.createOrEditRoleModalSaved', function () {
getCategories();
});
getCategories();
});
})();