I ended up getting it to work, but I now want to Implement a GenericAppService. But its throwing this error:
Castle.MicroKernel.Handlers.HandlerException occurred HResult=0x80131500 Message=Can't create component 'MMC.Platform.Web.Areas.App.Controllers.RPIListenerQueueController' as it has dependencies to be satisfied.
'MMC.Platform.Web.Areas.App.Controllers.RPIListenerQueueController' is waiting for the following dependencies:
- Service 'MMC.Platform.Generic.GenericAppService`3[[MMC.Platform.DMPModels.RpilistenerQueue, MMC.Platform.Core, Version=4.1.0.0, Culture=neutral, PublicKeyToken=null],[MMC.Platform.DMPModels.RpilistenerQueue, MMC.Platform.Core, Version=4.1.0.0, Culture=neutral, PublicKeyToken=null],[System.Int16, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]' which was not registered.
Source=
public class
GenericAppService<TEntity, TEntityDTO, TPrimaryKeyType> :
AsyncCrudAppService<TEntity, TEntityDTO, TPrimaryKeyType, TEntityDTO, TEntityDTO, TEntityDTO, TEntityDTO,
TEntityDTO>, IGenericAppService<TEntityDTO, TPrimaryKeyType>
where TEntity : class, IEntity<TPrimaryKeyType> where TEntityDTO : IEntityDto<TPrimaryKeyType>
{
public GenericAppService(IRepository<TEntity, TPrimaryKeyType> repository) : base(repository)
{
}
public IQueryable GetAllQueryable()
{
return Repository.GetAll();
}
}
public interface IGenericAppService<TEntity, TPrimaryKeyType> : IAsyncCrudAppService<TEntity, TPrimaryKeyType,
TEntity, TEntity, TEntity, TEntity, TEntity> where TEntity : IEntityDto<TPrimaryKeyType>
{
IQueryable GetAllQueryable();
}
public abstract class TelerikCRUDPlatformControllerBase<TEntity, TEntityDTO, TPrimaryKeyType> : PlatformControllerBase
where TEntity : AuditBase<TPrimaryKeyType> where TEntityDTO : IEntityDto<TPrimaryKeyType>
{
private readonly GenericAppService<TEntity, TEntityDTO, TPrimaryKeyType> _appService;
private string _deletePermission;
private string _createPermission;
private string _editPermission;
private string _readPermission;
protected TelerikCRUDPlatformControllerBase(GenericAppService<TEntity, TEntityDTO, TPrimaryKeyType> appService)
{
_appService = appService;
}
public virtual ActionResult Index()
{
return View();
}
public virtual JsonResult Read([DataSourceRequest] DataSourceRequest request)
{
if (!PermissionChecker.IsGranted(_readPermission))
{
throw new AbpAuthorizationException("You are not authorized to view/read!"); //ToDo: Create Localization
}
return Json(_appService.GetAllQueryable().ToDataSourceResult(request));
}
[HttpPost]
[DontWrapResult]
public virtual async Task<ActionResult> Create([DataSourceRequest] DataSourceRequest request, TEntityDTO entity)
{
if (!PermissionChecker.IsGranted(_createPermission))
{
throw new AbpAuthorizationException("You are not authorized to create!"); //ToDo: Create Localization
}
if (ModelState.IsValidWithNoAuditFieldsSet())
await _appService.Create(entity);
return Json(new[] {entity}.ToDataSourceResult(request, ModelState));
}
[HttpPost]
[DontWrapResult]
public virtual async Task<ActionResult> Update([DataSourceRequest] DataSourceRequest request, TEntityDTO entity)
{
if (!PermissionChecker.IsGranted(_editPermission))
{
throw new AbpAuthorizationException("You are not authorized to edit!"); //ToDo: Create Localization
}
if (ModelState.IsValidWithNoAuditFieldsSet())
await _appService.Update(entity);
return Json(new[] {entity}.ToDataSourceResult(request, ModelState));
}
[HttpPost]
[DontWrapResult]
public virtual async Task<ActionResult> Destroy([DataSourceRequest] DataSourceRequest request, TEntityDTO entity)
{
if (!PermissionChecker.IsGranted(_deletePermission))
{
throw new AbpAuthorizationException("You are not authorized to delete!"); //ToDo: Create Localization
}
await _appService.Delete(entity);
return Json(new[] {entity}.ToDataSourceResult(request, ModelState));
}
[HttpPost]
public ActionResult Telerik_Export(string contentType, string base64, string fileName)
{
var fileContents = Convert.FromBase64String(base64);
return File(fileContents, contentType, fileName);
}
}
Controller works if I make a normal AppService and derive from the CrudAsync
public class RPIListenerQueueController : TelerikCRUDPlatformControllerBase<RpilistenerQueue, RpilistenerQueue, short>
{
//private IRPIListenerQueueAppService _appService;
private string _deletePermission;
private string _createPermission;
private string _editPermission;
private string _readPermission;
//public RPIListenerQueueController(IRPIListenerQueueAppService appService)
//{
// _appService = appService;
//}
//public virtual ActionResult Index()
//{
// return View();
//}
//public virtual JsonResult Read([DataSourceRequest] DataSourceRequest request)
//{
// if (!PermissionChecker.IsGranted(_readPermission))
// {
// throw new AbpAuthorizationException("You are not authorized to view/read!"); //ToDo: Create Localization
// }
// return Json(_appService.GetAllQueryable().ToDataSourceResult(request));
//}
//[HttpPost]
//[DontWrapResult]
//public virtual async Task<ActionResult> Create([DataSourceRequest] DataSourceRequest request, RpilistenerQueue entity)
//{
// if (!PermissionChecker.IsGranted(_createPermission))
// {
// throw new AbpAuthorizationException("You are not authorized to create!"); //ToDo: Create Localization
// }
// if (ModelState.IsValidWithNoAuditFieldsSet())
// await _appService.Create(entity);
// return Json(new[] { entity }.ToDataSourceResult(request, ModelState));
//}
//[HttpPost]
//[DontWrapResult]
//public virtual async Task<ActionResult> Update([DataSourceRequest] DataSourceRequest request, RpilistenerQueue entity)
//{
// if (!PermissionChecker.IsGranted(_editPermission))
// {
// throw new AbpAuthorizationException("You are not authorized to edit!"); //ToDo: Create Localization
// }
// if (ModelState.IsValidWithNoAuditFieldsSet())
// await _appService.Update(entity);
// return Json(new[] { entity }.ToDataSourceResult(request, ModelState));
//}
//[HttpPost]
//[DontWrapResult]
//public virtual async Task<ActionResult> Destroy([DataSourceRequest] DataSourceRequest request, RpilistenerQueue entity)
//{
// if (!PermissionChecker.IsGranted(_deletePermission))
// {
// throw new AbpAuthorizationException("You are not authorized to delete!"); //ToDo: Create Localization
// }
// await _appService.Delete(entity);
// return Json(new[] { entity }.ToDataSourceResult(request, ModelState));
//}
//[HttpPost]
//public ActionResult Telerik_Export(string contentType, string base64, string fileName)
//{
// var fileContents = Convert.FromBase64String(base64);
// return File(fileContents, contentType, fileName);
//}
public RPIListenerQueueController(GenericAppService<RpilistenerQueue, RpilistenerQueue, short> appService) : base(appService)
{
}
}
NM, by me adding it to the bundleconfig and right clicking minifiy it was adding it again and messing something up.
Yeah, if use the javascript method it give me the filter is null error.
Heres the MVC Core version that I got working.... Finally after I realized they changed the default serializer to camelCase lol
@(Html.Kendo().Grid<UserListDto>()
.Name("Grid")
.Columns(columns =>
{
columns.Bound(p => p.Name);
columns.Bound(p => p.Surname);
columns.Bound(p => p.IsActive);
})
//.ToolBar(toolbar => {
// toolbar.Create();
// toolbar.Save();
//})
//.Editable(editable => editable.Mode(GridEditMode.InCell))
.Pageable()
.Mobile(MobileMode.Auto)
.Navigatable()
.Sortable()
.Scrollable()
.Filterable()
.ColumnMenu()
.DataSource(dataSource => dataSource
.Custom()
.PageSize(20)
.Schema(schema => schema.Data("result.items").Total("result.totalCount").Errors("result.error")
.Model(m =>
{
m.Id(x => x.Id);
m.Field(x => x.Name).From("name");
m.Field(x => x.Surname).From("surname");
m.Field(x => x.IsActive).From("isActive");
}))
.Transport(transport =>
{
transport.Read(read =>
read.Url("http://localhost:62114/api/services/app/User/GetUsers")
);
})
))
Heres a more enhanced version
@using MMC.Platform.Authorization.Users.Dto
@{
ViewData["Title"] = "View";
}
@(Html.Kendo().Grid<UserListDto>()
.Name("Grid")
.Columns(columns =>
{
columns.Bound(p => p.UserName).Title(@L("UserName"));
columns.Bound(p => p.Name).Title(@L("Name"));
columns.Bound(p => p.Surname).Title(@L("Name"));
columns.Bound(p => p.Roles).Title(@L("Roles")).ClientTemplate("#= getRoleNames(Roles)#");
columns.Bound(p => p.EmailAddress).Title(@L("EmailAddress"));
columns.Bound(p => p.IsEmailConfirmed).Title(@L("EmailConfirm"))
.ClientTemplate("#if(IsEmailConfirmed) {# <span class='label label-success'> #= app.localize('Yes') # </span>#} else {# <span class='label label-default'> #= app.localize('No') # </span>#}#")
.Filterable(filterable => filterable.Messages(m => m.IsFalse(@L("No"))).Messages(m => m.IsTrue(@L("Yes"))));
columns.Bound(p => p.IsActive).Title(@L("Active"))
.ClientTemplate("#if(IsActive) {# <span class='label label-success'> #= app.localize('Yes') # </span>#} else {# <span class='label label-default'> #= app.localize('No') # </span>#}#")
.Filterable(filterable =>filterable.Messages(m=>m.IsFalse(@L("No"))).Messages(m=>m.IsTrue(@L("Yes"))));
columns.Bound(p => p.LastLoginTime).Title(@L("LastLoginTime")).ClientTemplate("#= moment(LastLoginTime).format('L')#");
columns.Bound(p => p.CreationTime).Title(@L("CreationTime")).ClientTemplate("#= moment(CreationTime).format('L')#");
})
//.ToolBar(toolbar => {
// toolbar.Create();
// toolbar.Save();
//})
//.Editable(editable => editable.Mode(GridEditMode.InCell))
.Pageable()
.Mobile(MobileMode.Auto)
.Navigatable()
.Sortable()
.Scrollable()
.Filterable()
.ColumnMenu()
.DataSource(dataSource => dataSource
.Custom()
.PageSize(20)
.Schema(schema => schema.Data("result.items").Total("result.totalCount").Errors("result.error")
.Model(m =>
{
m.Id(x => x.Id);
m.Field(x => x.Name).From("name");
m.Field(x => x.Surname).From("surname");
m.Field(x => x.UserName).From("userName");
m.Field(x => x.Roles).From("roles");
m.Field(x => x.EmailAddress).From("emailAddress");
m.Field(x => x.IsEmailConfirmed).From("isEmailConfirmed");
m.Field(x => x.IsActive).From("isActive");
m.Field(x => x.LastLoginTime).From("lastLoginTime");
m.Field(x => x.CreationTime).From("creationTime");
}))
.Transport(transport =>
{
transport.Read(read =>
read.Url("http://localhost:62114/api/services/app/User/GetUsers")
);
})
))
<script>
function getRoleNames(roles) {
var roleNames = '';
for (var j = 0; j < roles.length; j++) {
if (roleNames.length) {
roleNames = roleNames + ', ';
}
roleNames = roleNames + roles[j].roleName;
};
return roleNames;
}
</script>
Can you also make an example using the MVC helpers. The intellisense is way better when trying to remember all of Teleriks toggles :)
Thanks, that was it.
Can you guys provide a GIST/small project that implements this. I need to be able to login as a tenant and run an app service.
I tried copying your test project and swapping out the ServiceCollectionRegistrar but it throws an error.
This gets me half way there:
public static void Register(IIocManager iocManager)
{
RegisterIdentity(iocManager);
var builder = new DbContextOptionsBuilder<PlatformDbContext>();
builder.UseSqlServer("Server=mmcsqldev02; Database=MMCPlatformControl_BradV2; Trusted_Connection=True;", o => o.UseRowNumberForPaging());
iocManager.IocContainer.Register(
Component
.For<DbContextOptions<PlatformDbContext>>()
.Instance(builder.Options)
.LifestyleSingleton()
);
}
How do I make this change the connection to the clients db now, I'm missing something to change the ctx?
protected void LoginAsTenant(string tenancyName, string userName)
{
AbpSession.TenantId = null;
var tenant = UsingDbContext(context => context.Tenants.FirstOrDefault(t => t.TenancyName == tenancyName));
if (tenant == null)
{
throw new Exception("There is no tenant: " + tenancyName);
}
AbpSession.TenantId = tenant.Id;
if (string.IsNullOrEmpty(tenant.ConnectionString))
{
var user = UsingDbContext(
context => context.Users.FirstOrDefault(
u => u.TenantId == AbpSession.TenantId && u.UserName == userName));
if (user == null)
{
throw new Exception("There is no user: " + userName + " for tenant: " + tenancyName);
}
AbpSession.UserId = user.Id;
}
else
{
var connString = SimpleStringCipher.Instance.Decrypt(tenant.ConnectionString);
var builder = new DbContextOptionsBuilder<PlatformDbContext>();
builder.UseSqlServer(connString, o => o.UseRowNumberForPaging());
var ctx = new PlatformDbContext(builder.Options);
var user = UsingDbContext(
context => context.Users.FirstOrDefault(
u => u.TenantId == AbpSession.TenantId && u.UserName == userName));
if (user == null)
{
throw new Exception("There is no user: " + userName + " for tenant: " + tenancyName);
}
AbpSession.UserId = user.Id;
}
}
Shouldn't there be an easier way to test our app services using real data? No one in their right mind is going to mock up data for every table they have.
Ideally I just want to say use this app service using this db context/connection string.
I'm not looking to run the test cases for all the stuff you guys wrote, its more for my own stuff.
ASP.NET Core
You and bunch of other people are still waiting for a reply on this :)