dotnet-core, angular, 5.4.1 I implement Entity History in ProjectnameEntityFrameworkCoreModule (I am tracking history for all fully audited entities):
Configuration.EntityHistory.IsEnabled = true; //Enable this to write change logs for the entities below:
Configuration.EntityHistory.Selectors.Add("NuagecareEntities", typeof(OrganizationUnit), typeof(Role), typeof(User), typeof(Tenant));
Configuration.EntityHistory.Selectors.Add(
new NamedTypeSelector(
"Abp.FullAuditedEntities",
type => typeof(IFullAudited).IsAssignableFrom(type)
));
In my system a tenant is able to implement a data provider and the system will use Hangfire to invoke a background job to get data changes made in the data provider database. My entity (NcEntity) is made up of two properties, DisplayName and ExtensionData. The latter is a collection of properties in Json format implemented with the IExtendableObject interface. My DataProviderAPIService class receives data from the data provider, deserialises it and carries out an update, insert or soft-delete, the code below shows the update method, code simplified:
if (ncEntity.DisplayName != entity.DisplayName || ncEntity.ExtensionData != entity.ExtensionData)
{
ncEntity.DisplayName = entity.DisplayName;
ncEntity.ExtensionData = entity.ExtensionData;
}
_ncEntityRepository.Update(ncEntity);
This works aok in terms of updating data but it does not invoke entity history, I have no entry in the entity history tables. If I use the user interface and edit an entity by, for example, changing the DisplayName property the change is captured in entity history. I have read the documentation at [https://aspnetboilerplate.com/Pages/Documents/Entity-History]) but can find no pointers as to where i am going wrong. The question is:
How do I implement entity history in a ServiceAPI?
Previous title: Notifications
I add the notification to AppNotificationNames:
public const string DataProviderUpdateCompleted = "App.DataProviderUpdateCompleted";
I then add the notification to AppNotificationProvider:
context.Manager.Add(
new NotificationDefinition(
AppNotificationNames.DataProviderUpdateCompleted,
displayName: L("DataProviderUpdatedNotificationDefinition"),
permissionDependency: new SimplePermissionDependency(AppPermissions.Pages_Administration_Users)
)
);
I then add a message to my localization file:
<text name="DataProviderUpdatedNotificationMessage"><![CDATA["Database updated from data provider:</br>updated; {entitiesUpdated} </br>added; {entitiesAdded} </br>moved; {entitiesMoved}."]]></text>
The notification displays fine as html but the row in the notifications grid displays text and not html (as does the notification on my desktop):
Database updated from data provider:</br>updated; 0 </br>added; 0 </br>moved; 0.
The question is:
How do I universally format notifications?
dotnet-core, angular, 5.4.1 What's the position with regard to the Hangfire dashboard in the above configuration? I seem to remember that it's not possible to get it working because _Hangfire_uses cookies. Is this true or is there a simple way to get the _Hangfire_dashboard working?
Anyone - best practices for integrating Hangfire in dotnet-core, angular version. Follow the instructions at [https://aspnetboilerplate.com/Pages/Documents/Hangfire-Integration]). Normally in an MVC project I place this in StartUp.cs:
Services.Hangfire.ConfigureHangfire(app);
And then in my services layer I would place the service:
public class Hangfire
{
public static void ConfigureHangfire(IAppBuilder app)
{
GlobalConfiguration.Configuration.UseSqlServerStorage("DefaultConnection");
//see https://blog.entelect.co.za/view/7580/dependency-injection-with-hangfire
var hangfireContainer = new UnityContainer();
GlobalConfiguration.Configuration.UseActivator(new UnityJobActivator(hangfireContainer));
app.UseHangfireServer();
app.UseHangfireDashboard("/backgroundjobs", new DashboardOptions
{
Authorization = new[] { new HangfireAuthorization() }
});
if (ConfigurationManager.AppSettings["IsProduction"] == "true")
{
InitializeJobs();
}
}
public static void InitializeJobs()
{
//place any recurring jobs here....
RecurringJob.AddOrUpdate<Services.Workers.RebuildCoursesAndEventsJob>(job => job.Execute(), "0 7 * * *");
}
}
public class HangfireAuthorization : IDashboardAuthorizationFilter
{
public bool Authorize([NotNull] DashboardContext context)
{
if (HttpContext.Current.User != null && HttpContext.Current.User.Identity.IsAuthenticated)
{
var authorized = (HttpContext.Current.User.IsInRole("Developer") || HttpContext.Current.User.IsInRole("Admin"));
return authorized;
}
return false;
}
}
And RebuildCoursesAndEventsJob would be run as follows (note: the system uses CQS):
public class RebuildCoursesAndEventsJob
{
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private ICommandHandler<RebuildCoursesAndEventsCommand> _rebuildCoursesAndEvents;
public RebuildCoursesAndEventsJob(
ICommandHandler<RebuildCoursesAndEventsCommand> rebuildCoursesAndEvents)
{
_rebuildCoursesAndEvents = rebuildCoursesAndEvents;
}
public void Execute()
{
logger.Info("executing job: " + DateTime.Now.ToShortTimeString(), null);
using (DomainContext _db = new DomainContext())
{
var service = new RebuildCoursesAndEventsCommand();
_rebuildCoursesAndEvents.Handle(service);
return;
}
}
}
Now how the hell would I do that in Zero? I get the part about not being able to use the dashboard because of MVC's cookies. I'm not sure how Castle works, I had to create a UnityContainer for Hangfire when placing it in my service project in MVC as the code above shows. So the question is;
what do I place in my Startup.cs to fire the service, where do I put my service, where do I place my workers (jobs) and what code do I need to make it all work with Zero and Castle?
asp-core, angular: 5.4.1 Hey guys,
I followed the instructions at [https://medium.com/volosoft/devextreme-asp-net-zero-integration-444ea26d0fc5]) to implement a couple of DevExtreme components a while back on 5.1.0. It is worth noting that as of Angular 6 the instructions for implementation of DevExtreme in Angular 6 and above have changed. Therefore your blog will not work with 5.4.0 and above.
Instead of adding the following lines to your .angular-cli.json file:
"../node_modules/devextreme/dist/css/dx.common.css",
"../node_modules/devextreme/dist/css/dx.light.css",
One should instead add the following lines to your angular.json file:
"node_modules/devextreme/dist/css/dx.common.css",
"node_modules/devextreme/dist/css/dx.light.css",
This is as per their instructions at the following address: [https://github.com/DevExpress/devextreme-angular/blob/master/docs/using-angular-cli.md#configuration]). You may want to update the blog to save irrelevant issues being posted to github which seems to have replaced your forum as the go-to "can you help me with..." site.
.Net core, angular, 5.4.0 I download the new version and set up as per instructions. I login as the default tenant and add a new Organization Unit. I go to Audit Logs and can see the Operation for CreateOrganizationUnit in the Operation log tab. I switch tabs to Change logs and can not see the creation, I select the admin user and the OrganizationUnit entity and can still not see any changes. I update the Organization Unit and return to the Audit Log -> Change log tab and can still not see any changes.
Am I missing something?
When I do a build with
ng build -prod
I end up with a very large metronic folder in the assets folder including all of the source for all the demos.
Is there any way I can remove these folder from the build process?
What are they there for?
aspnet core, angular 5.1.0 I implement generic tree builder methods using the code here: [https://stackoverflow.com/questions/19648166/nice-universal-way-to-convert-list-of-items-to-tree]) Which implements the following:
public class TreeItem<T>
{
public T Item { get; set; }
public IEnumerable<TreeItem<T>> Children { get; set; }
}
using the following generic helper:
public static IEnumerable<TreeItem<T>> GenerateTree<T, K>(
this IEnumerable<T> collection,
Func<T, K> id_selector,
Func<T, K> parent_id_selector,
K root_id = default(K))
{
foreach (var c in collection.Where(c => parent_id_selector(c).Equals(root_id)))
{
yield return new TreeItem<T>
{
Item = c,
Children = collection.GenerateTree(id_selector, parent_id_selector, id_selector(c))
};
}
}
I then implement this in my service:
public async Task<List<TreeItem<NcActionDto>>> GetAllAsTree()
{
var query = _ncActionRepository.GetAll();
var ncActions = await query
.ToListAsync();
var actionTree = ncActions.GenerateTree(m => m.Id, m => m.ParentId);
return ObjectMapper.Map<List<TreeItem<NcActionDto>>> (actionTree);
}
I can run this successfully using the swagger interface but when I come to refresh my service proxies it is not present.
Is there any reason why the nswag generation should not pick up this method?
aspnet-core angular, 5.1.0 In my host have a root organization unit for templates. During tenant registration these templates are displayed as a drop down list. The tenant selects a template option and the required entities for the template should be loaded for the tenant. I load the relevant entities from the host. So far so good. I then try save these entities for the registration tenant but the system throws an error. The repository seems to have no .AsNoTracking() option My question is: How do I clone an identity list with the Zero repository?
I have been blindly following standards laid out from code generated by the RAD tool (which is such a time saver, thanks guys) when I noticed the following method:
[AbpAuthorize(AppPermissions.Pages_Test_Edit)]
private async Task Update(CreateOrEditTestDto input)
{
var test = await _testRepository.FirstOrDefaultAsync((int)input.Id);
ObjectMapper.Map(input, test);
}
This works but I am little confused as to where the update method in the repository is called, I was expecting to see something like:
[AbpAuthorize(AppPermissions.Pages_Test_Edit)]
private async Task Update(CreateOrEditTestDto input)
{
var test = await _testRepository.FirstOrDefaultAsync((int)input.Id);
...
await _testRepository.UpdateAsync(ObjectMapper.Map(input, test));
}
What is the magic with the generated code from the RAD tool? Where is the update called? Can someone point me to some documentation here because this surprised me!