Raise notification from within service?

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
7 Jahre weitere
Is there a way to show a notification on the frontend on some actions inside a service.

For example: I create a plugin that overwrites the IProductService to check when a product is created there are already x number of products, if so I want to prevent the user from creating another product. I just can't throw an exception as I do not wish to display a YSOD or even an error notification in the frontend.

I understand that the display of notifications is something that can be controlled in controllers, but I don't want to create a new (or override a) controller for this to happen.
7 Jahre weitere
Yes, see how it's done for Product configuration field "Maximum cart qty".
7 Jahre weitere
How does that help? The code you refer to has got a Warnings property on it that is being used by the controller, but the ProductService.InsertProduct does only take a Product which does not have this Warnings property. I don't want to change the Entity to include this property.

As far as I can see there is nog generic way to transport "warnings or messages" occured in the services back to the frontend.
7 Jahre weitere
I'm relatively new to this thing also, so take this with a grain of salt, but it seems to me (from looking at the existing code) that this is relatively intentional.

errors at the services "layers" are generally logged and not surfaced to the user.

there are however a (large) handful of exceptions to this however it looks like its the CONTROLLERS job to decide this... thus the last response was guiding you to the way its been done in the shopping cart services which is 'build a list of strings to show the user and pass it back via a known function for Getting Warnings' - its not a generic approach because it requires the end model to have a model for displaying warnings to the user, not all pages have this, however they (most/all?) have a way of handling "NotifyType" entries in ViewData/TempData.

IMO this is kind of stupid but whatever... it'd be really nice if you could just get at it from something like "WebHelper" or "WorkContext" (since they wrap the HTTPCONTEXT)  but (at least in 3.7) i cant figure out how without modifiying them... which I'm generally reluctant to do too often.

I *feel* like its done this way generally for security, but also because services could run headless I guess and therefore shouldn't really be "allowed" to decide whether to show a user an error or not (and so the framework guides you on this by making it the responsibilty of the controller)... guessing most of this...

If i understand correctly what you are wanting then:
The cheaters way of getting around this without modifying the "nop platform" is to "find" the nearest controller and hack into the "View/Temp" Data with a copy of the "AddNotification" function... as I mentioned above...
... the only problem with this is that in most SERVICES there is (as I mentioned) no exposure of things like httpcontext/Response objects...

BUT you can always perform the ultimate sin of:

System.Web.HttpContext.Current.items that duplicates the AddNotification() function in BaseController... and then override "Views\Shared\_Notifications.cshtml" to have some code like
(NOTE: that its not as "smart" as view/temp data in that it just persists in the session until it hits this code and is "viewed"...)

eg: somewhere generally accessible:
       public static void GenericAddNotification(NotifyType type, string message)
        {
            var sessionItems = System.Web.HttpContext.Current.Items;

            string dataKey = string.Format("mynop.notifications.{0}", type);

                if (sessionItems[dataKey] == null)
                    sessionItems[dataKey] = new List<string>();
                ((List<string>)sessionItems[dataKey]).Add(message);
            
            
        }

then in _Notification.cshtml add this after the other "View/Temp" data extraction into "success/error" message lists...


    //not as elegant as using TEmp/Viewdata but allows notifications to be set from anywhere you can get to HttpContext...
    var sessionItems = System.Web.HttpContext.Current.Items;
    if (sessionItems[string.Format("mynop.notifications.{0}", NotifyType.Success)] != null)
    {
        successMessages.AddRange(sessionItems[string.Format("mynop.notifications.{0}", NotifyType.Success)] as IList<string>);
        sessionItems.Remove(string.Format("mynop.notifications.{0}", NotifyType.Success));
    }
    if (sessionItems[string.Format("mynop.notifications.{0}", NotifyType.Error)] != null)
    {
        errorMessages.AddRange(sessionItems[string.Format("mynop.notifications.{0}", NotifyType.Error)] as IList<string>);
        sessionItems.Remove(string.Format("mynop.notifications.{0}", NotifyType.Error));
    }

then you just wrap your "problems" in service or plugins or whatever in
try{
  ...dangerous code here
}
catch(SomeException ex)
{
logger.Log... - so you can find the details in System.Log
GenericAddNotification(NotifyType.Error, "WHAT!? You broke it?!")
}

horrible but does work...
And remember that SOME controller actions do already do this try/catch "AddNotification" so be aware of "where you are calling this" from... ie context of your service calls.

This is probably a terrible approach, but it gets ME over the line... so... YMMV
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.