OrchardCMS / OrchardCore

Orchard Core is an open-source modular and multi-tenant application framework built with ASP.NET Core, and a content management system (CMS) built on top of that framework.
https://orchardcore.net
BSD 3-Clause "New" or "Revised" License
7.41k stars 2.39k forks source link

How to block a content item when you remove it, and give friendly hints. #6725

Open chinasqzl opened 4 years ago

chinasqzl commented 4 years ago

image

image

hishamco commented 4 years ago

I think you can use content events for that

chinasqzl commented 4 years ago

@hishamco Don't understand, when the event is triggered, the deletion is complete. Is there an example in the source code?

hishamco commented 4 years ago

There are many event for the content such as: created, loaded, removed .. etc, have a look to https://github.com/OrchardCMS/OrchardCore/blob/dev/src/OrchardCore/OrchardCore.ContentManagement/Handlers/ContentsHandler.cs

chinasqzl commented 4 years ago

@hishamco Blocking deletions is determined by the parts business, and using content events is not good.

hishamco commented 4 years ago

I didn't under stand you, and how telling that using content events is not good?!!

chinasqzl commented 4 years ago

InStockPicking (contentType) -TitlePart -StockPickingPart

Stock picking part, after publication, can not be deleted, can not be modified. Non-removable properties are determined by the part, so should be written in the part's StockPickingPartHandler.RemovingAsync.

In content events, i want to determine whether StockPickingPart is included?

sebastienros commented 4 years ago

the content admin controller needs to check if the ModelState is valid before invoking RemoveAsync(), and call session.Cancel() if not.

https://github.com/OrchardCMS/OrchardCore/blob/dev/src/OrchardCore.Modules/OrchardCore.Contents/Controllers/AdminController.cs#L583

I think it's up to the called or RemoveAsync (or UpdateAsync) to check for ModelState errors and cancel the transaction or display error messages.

sebastienros commented 4 years ago

As a mitigation, you can call _session.Cancel() until we fix the issue. That will prevent the database from being committed. Yo ucan also use INotifier to render an error message.

hung-doan commented 3 years ago

@sebastienros I used the _session.Cancel() as a work around and found 2 issues:

  1. I received two notification: one is the default success message; one for my custom error message. => Which cause the confusion to users. Is there any way to only show my error notification ?.

image

  1. _session.Cancel() doesn't work for Media field. The record deletion in the data is cancelled, however the media associate with it is deleted. Is there any workaround for this ?. Or is there any way to call my custom API for the deletion?.
jtkech commented 3 years ago

We have some helpers that we already use in some places, allowing to execute things through delegates, but only if the session was not canceled, and moreover only if the session was committed sucessfully. They are useful when doing things not directly related to the ambient session, but still correlated to a content item being updated, as in your case ;)

We already added recently this pattern in some places, but yes there are some remaining places that still need to be adapted, e.g. here i think some media handlers, I will take a look on this issue more in details this night