OneSignal / onesignal-dotnet-api

Other
13 stars 12 forks source link

[Bug]: Notifcation appId cannot be null when using in ASP.NET #37

Open licon4812 opened 1 year ago

licon4812 commented 1 year ago

What happened?

The latest stable version of the library returns the following error

System.ArgumentNullException: Value cannot be null. (Parameter 'appId is a required property for Notification and cannot be null')

Steps to reproduce?

1. Install Nuget Package "OneSignalApi" Version="2.0.0"
2. Create a service in the folder Services with the following

using OneSignalApi.Api;
using OneSignalApi.Client;
using OneSignalApi.Model;
using static System.Net.WebRequestMethods;

namespace AWC.Web.Services;

public class OneSignalService
{
    private readonly DefaultApi _client;
    private string _appId;
    public OneSignalService(string appId,string oneSignalApiKey)
    {
        _appId = appId;
        var appConfig = new Configuration
        {
            BasePath = "https://onesignal.com/api/v1",
            AccessToken = oneSignalApiKey
        };
        _client = new DefaultApi(appConfig);
    }

    public async Task SendNotification(string name, string message)
    {
        //create notification 
        var notification = new Notification
        {
            AppId = _appId,
            Name = name,
            Headings = new StringMap(en: "Heading"),
            SmallIcon = "@mipmap/appicon",
            Contents = new StringMap(en: message),
            IncludedSegments = new List<string> { "Subscribed Users" },
        };
        var response = await _client.CreateNotificationAsync(notification);
        Console.WriteLine(response);
    }
}

3. Register Service in Program.cs

var oneSignalAppId = builder.Configuration.GetSection("Secrets")["OneSignalAppId"];
var oneSignalApiKey = builder.Configuration.GetSection("Secrets")["OneSignalApIKey"];
builder.Services.AddSingleton(new OneSignalService(oneSignalAppId!,oneSignalApiKey!));

4. Use service in controller

public class MyController : ControllerBase
{
    private readonly OneSignalService _oneSignalService;

    public MyController(OneSignalService oneSignalService)
    {
        _oneSignalService = oneSignalService;
    }

    [HttpPost]
    public async Task<ActionResult> SendNotification([FromBody] string message)
    {
        await _oneSignalService.SendNotification("Heading", "message");

        return Ok();
    }
}

### What did you expect to happen?

I expected the notification to be sent correctly as appId is not null. 
I confirmed as much but don't want to post my secrets here

### Relevant log output

```Shell
System.ArgumentNullException: Value cannot be null. (Parameter 'appId is a required property for Notification and cannot be null')
         at OneSignalApi.Model.Notification..ctor(List`1 includedSegments, List`1 excludedSegments, List`1 includePlayerIds, List`1 includeExternalUserIds, List`1 includeEmailTokens, List`1 includePhoneNumbers, List`1 includeIosTokens, List`1 includeWpWnsUris, List`1 includeAmazonRegIds, List`1 includeChromeRegIds, List`1 includeChromeWebRegIds, List`1 includeAndroidRegIds, PlayerNotificationTargetIncludeAliases includeAliases, Nullable`1 targetChannel, String id, String name, Nullable`1 isIos, Nullable`1 isAndroid, Nullable`1 isHuawei, Nullable`1 isAnyWeb, Nullable`1 isChromeWeb, Nullable`1 isFirefox, Nullable`1 isSafari, Nullable`1 isWPWNS, Nullable`1 isAdm, Nullable`1 isChrome, String channelForExternalUserIds, String appId, String externalId, StringMap contents, StringMap headings, StringMap subtitle, Object data, String huaweiMsgType, String url, String webUrl, String appUrl, Object iosAttachments, String templateId, Nullable`1 contentAvailable, Boolean mutableContent, String targetContentIdentifier, String bigPicture, String huaweiBigPicture, String admBigPicture, String chromeBigPicture, String chromeWebImage, List`1 buttons, List`1 webButtons, String iosCategory, String androidChannelId, String huaweiChannelId, String existingAndroidChannelId, String huaweiExistingChannelId, BasicNotificationAllOfAndroidBackgroundLayout androidBackgroundLayout, String smallIcon, String huaweiSmallIcon, String largeIcon, String huaweiLargeIcon, String admSmallIcon, String admLargeIcon, String chromeWebIcon, String chromeWebBadge, String firefoxIcon, String chromeIcon, String iosSound, String androidSound, String huaweiSound, String admSound, String wpWnsSound, String androidLedColor, String huaweiLedColor, String androidAccentColor, String huaweiAccentColor, Nullable`1 androidVisibility, Nullable`1 huaweiVisibility, String iosBadgeType, Nullable`1 iosBadgeCount, String collapseId, String webPushTopic, Object apnsAlert, String delayedOption, String deliveryTimeOfDay, Nullable`1 ttl, Nullable`1 priority, String apnsPushTypeOverride, String throttleRatePerMinute, String androidGroup, String androidGroupMessage, String admGroup, Object admGroupMessage, String threadId, String summaryArg, Int32 summaryArgCount, String emailSubject, String emailBody, String emailFromName, String emailFromAddress, String smsFrom, List`1 smsMediaUrls, List`1 filters, Nullable`1 sendAfter)
         at AWC.Web.Services.OneSignalService.SendNotification(String name, String message) in D:\Programming\The AWC\The-AWC-App\backend\AWC.Web\Services\OneSignalService.cs:line 26
         at AWC.Web.Controllers.NewsPostsController.PostNewsPost(NewsPost newsPost) in D:\Programming\The AWC\The-AWC-App\backend\AWC.Web\Controllers\NewsPostsController.cs:line 97
         at lambda_method6(Closure, Object)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
         at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
         at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

Code of Conduct

licon4812 commented 1 year ago

I see this is due to the Notification Model not supporting object initialization via the properties, but instead, I have to use it via the constructor.

I had to use an older style of OOP as opposed to modern day OOP in .NET

Original


public async Task SendNotification(string name, string heading, string message)
    {
        //create notification 
        var notification = new Notification
        {
            AppId = _appId,
            Name = name,
            Headings = new StringMap(en: heading),
            SmallIcon = "@mipmap/appicon",
            Contents = new StringMap(en: message),
            IncludedSegments = new List<string> { "Subscribed Users" },
        };
        var response = await _client.CreateNotificationAsync(notification);
        Console.WriteLine(response);
    }

Fix

public async Task SendNotification(string name, string heading, string message)
    {
        //create notification 
        var notification = new Notification(
            appId: _appId, 
            name: name, 
            headings: new StringMap(en: heading),
            smallIcon: "@mipmap/appicon", 
            contents: new StringMap(en: message),
            includedSegments: new List<string> { "Subscribed Users" }
        );
        var response = await _client.CreateNotificationAsync(notification);
        Console.WriteLine(response);
    }