次の方法で共有


Azure Functions における SignalR Service の出力バインド

SignalR 出力バインドを使用して、Azure SignalR Service で 1 つ以上のメッセージを送信します。 次の宛先にメッセージをブロードキャストできます。

  • 接続されているすべてのクライアント
  • 指定したグループ内の接続済みクライアント
  • 特定のユーザーに対して認証された接続されているクライアント

出力バインドを使用すると、グループを管理することもできます。たとえば、グループへのクライアントまたはユーザーの追加、グループからのクライアントまたはユーザーの削除などです。

セットアップと構成の詳細については、概要に関するページをご覧ください。

すべてのクライアントにブロードキャストする

A C# 関数は、次の C# モードのいずれかを使用して作成できます。

  • 分離されたワーカー モデル: ランタイムから分離されたワーカー プロセスで実行されるコンパイル済みの C# 関数。 分離ワーカー プロセスは、LTS および 非 LTS バージョンの .NET および .NET Framework で実行されている C# 関数をサポートするために必要です。
  • インプロセス モデル: Functions ランタイムと同じプロセスで実行されるコンパイル済みの C# 関数。
  • C# スクリプト: Azure portal で C# 関数を作成するときに主に使用されます。

次の例は、出力バインドを使用してすべての接続済みクライアントにメッセージを送信する関数を示しています。 newMessage は、各クライアントで呼び出されるメソッドの名前です。

[Function(nameof(BroadcastToAll))]
[SignalROutput(HubName = "chat", ConnectionStringSetting = "SignalRConnection")]
public static SignalRMessageAction BroadcastToAll([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
{
    using var bodyReader = new StreamReader(req.Body);
    return new SignalRMessageAction("newMessage")
    {
        // broadcast to all the connected clients without specifying any connection, user or group.
        Arguments = new[] { bodyReader.ReadToEnd() },
    };
}

function.json ファイルのバインド データを次に示します。

function.json の例:

{
  "type": "signalR",
  "name": "signalROutput",
  "hubName": "hubName1",
  "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
  "direction": "out"
}
const { app, output } = require('@azure/functions');

const signalR = output.generic({
    type: 'signalR',
    name: 'signalR',
    hubName: 'hub',
    connectionStringSetting: 'AzureSignalRConnectionString',
});

// You can use any other trigger type instead.
app.http('broadcast', {
    methods: ['GET'],
    authLevel: 'anonymous',
    extraOutputs: [signalR],
    handler: (request, context) => {
        context.extraOutputs.set(signalR, {
            "target": "newMessage",
            "arguments": [request.body]
        });
    }
});

PowerShell の完全な例は保留中です。

Python コードを次に示します。

def main(req: func.HttpRequest, signalROutput: func.Out[str]) -> func.HttpResponse:
    message = req.get_json()
    signalROutput.set(json.dumps({
        'target': 'newMessage',
        'arguments': [ message ]
    }))
@FunctionName("sendMessage")
@SignalROutput(name = "$return", HubName = "hubName1")
public SignalRMessage sendMessage(
        @HttpTrigger(
            name = "req",
            methods = { HttpMethod.POST },
            authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Object> req) {

    SignalRMessage message = new SignalRMessage();
    message.target = "newMessage";
    message.arguments.add(req.getBody());
    return message;
}

ユーザーに送信する

ユーザーに対して認証された接続だけにメッセージを送信するには、SignalR メッセージの user ID を設定します。

[Function(nameof(SendToUser))]
[SignalROutput(HubName = "chat", ConnectionStringSetting = "SignalRConnection")]
public static SignalRMessageAction SendToUser([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
{
    using var bodyReader = new StreamReader(req.Body);
    return new SignalRMessageAction("newMessage")
    {
        Arguments = new[] { bodyReader.ReadToEnd() },
        UserId = "userToSend",
    };
}

function.json ファイルのバインド データを次に示します。

function.json の例:

{
  "type": "signalR",
  "name": "signalROutput",
  "hubName": "hubName1",
  "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
  "direction": "out"
}

PowerShell の完全な例は保留中です。

Python コードを次に示します。

def main(req: func.HttpRequest, signalROutput: func.Out[str]) -> func.HttpResponse:
    message = req.get_json()
    signalROutput.set(json.dumps({
        #message will only be sent to this user ID
        'userId': 'userId1',
        'target': 'newMessage',
        'arguments': [ message ]
    }))
@FunctionName("sendMessage")
@SignalROutput(name = "$return", HubName = "hubName1")
public SignalRMessage sendMessage(
        @HttpTrigger(
            name = "req",
            methods = { HttpMethod.POST },
            authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Object> req) {

    SignalRMessage message = new SignalRMessage();
    message.userId = "userId1";
    message.target = "newMessage";
    message.arguments.add(req.getBody());
    return message;
}
const { app, output } = require('@azure/functions');

const signalR = output.generic({
    type: 'signalR',
    name: 'signalR',
    hubName: 'hub',
    connectionStringSetting: 'AzureSignalRConnectionString',
});

app.http('sendToUser', {
    methods: ['GET'],
    authLevel: 'anonymous',
    extraOutputs: [signalR],
    handler: (request, context) => {
        context.extraOutputs.set(signalR, {
            "target": "newMessage",
            "arguments": [request.body],
            "userId": "userId1",
        });
    }
});

グループに送信する

グループに追加された接続だけにメッセージを送信するには、SignalR メッセージの group name を設定します。

[Function(nameof(SendToGroup))]
[SignalROutput(HubName = "chat", ConnectionStringSetting = "SignalRConnection")]
public static SignalRMessageAction SendToGroup([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
{
    using var bodyReader = new StreamReader(req.Body);
    return new SignalRMessageAction("newMessage")
    {
        Arguments = new[] { bodyReader.ReadToEnd() },
        GroupName = "groupToSend"
    };
}

function.json ファイルのバインド データを次に示します。

function.json の例:

{
  "type": "signalR",
  "name": "signalROutput",
  "hubName": "hubName1",
  "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
  "direction": "out"
}
const { app, output } = require('@azure/functions');

const signalR = output.generic({
    type: 'signalR',
    name: 'signalR',
    hubName: 'hub',
    connectionStringSetting: 'AzureSignalRConnectionString',
});

app.http('sendToGroup', {
    methods: ['GET'],
    authLevel: 'anonymous',
    extraOutputs: [signalR],
    handler: (request, context) => {
        context.extraOutputs.set(signalR, {
            "target": "newMessage",
            "arguments": [request.body],
            "groupName": "myGroup",
        });
    }
});

PowerShell の完全な例は保留中です。

Python コードを次に示します。

def main(req: func.HttpRequest, signalROutput: func.Out[str]) -> func.HttpResponse:
    message = req.get_json()
    signalROutput.set(json.dumps({
        #message will only be sent to this group
        'groupName': 'myGroup',
        'target': 'newMessage',
        'arguments': [ message ]
    }))
@FunctionName("sendMessage")
@SignalROutput(name = "$return", HubName = "hubName1")
public SignalRMessage sendMessage(
        @HttpTrigger(
            name = "req",
            methods = { HttpMethod.POST },
            authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Object> req) {

    SignalRMessage message = new SignalRMessage();
    message.groupName = "myGroup";
    message.target = "newMessage";
    message.arguments.add(req.getBody());
    return message;
}

グループ管理

SignalR Service を使用すると、ユーザーまたは接続をグループに追加できます。 その後にメッセージをグループに送信できます。 SignalR 出力バインドを使ってグループを管理することができます。

メンバーを追加または削除する SignalRGroupActionType を指定します。 次の例では、ユーザーをグループから削除します。

[Function(nameof(RemoveFromGroup))]
[SignalROutput(HubName = "chat", ConnectionStringSetting = "SignalRConnection")]
public static SignalRGroupAction RemoveFromGroup([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
{
    return new SignalRGroupAction(SignalRGroupActionType.Remove)
    {
        GroupName = "group1",
        UserId = "user1"
    };
}

Note

ClaimsPrincipal を正しくバインドするためには、Azure Functions で認証設定を構成しておく必要があります。

function.json ファイルのバインド データを次に示します。

function.json の例:

{
  "type": "signalR",
  "name": "signalROutput",
  "hubName": "hubName1",
  "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
  "direction": "out"
}
const { app, output } = require('@azure/functions');

const signalR = output.generic({
    type: 'signalR',
    name: 'signalR',
    hubName: 'hub',
    connectionStringSetting: 'AzureSignalRConnectionString',
});

// The following function adds a user to a group
app.http('addUserToGroup', {
    methods: ['POST'],
    authLevel: 'anonymous',
    extraOutputs: [signalR],
    handler: (request, context) => {
        context.extraOutputs.set(signalR, {
            "userId": req.query.userId,
            "groupName": "myGroup",
            "action": "add"
        });
    }
});

// The following function removes a user from a group
app.http('removeUserFromGroup', {
    methods: ['POST'],
    authLevel: 'anonymous',
    extraOutputs: [signalR],
    handler: (request, context) => {
        context.extraOutputs.set(signalR, {
            "userId": req.query.userId,
            "groupName": "myGroup",
            "action": "remove"
        });
    }
});

PowerShell の完全な例は保留中です。

次の例では、ユーザーをグループに追加します。

def main(req: func.HttpRequest, signalROutput: func.Out[str]) -> func.HttpResponse:
    signalROutput.set(json.dumps({
        'userId': 'userId1',
        'groupName': 'myGroup',
        'action': 'add'
    }))

次の例では、ユーザーをグループから削除します。

def main(req: func.HttpRequest, signalROutput: func.Out[str]) -> func.HttpResponse:
    signalROutput.set(json.dumps({
        'userId': 'userId1',
        'groupName': 'myGroup',
        'action': 'remove'
    }))

次の例では、ユーザーをグループに追加します。

@FunctionName("addToGroup")
@SignalROutput(name = "$return", HubName = "hubName1")
public SignalRGroupAction addToGroup(
        @HttpTrigger(
            name = "req",
            methods = { HttpMethod.POST },
            authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Object> req,
        @BindingName("userId") String userId) {

    SignalRGroupAction groupAction = new SignalRGroupAction();
    groupAction.action = "add";
    groupAction.userId = userId;
    groupAction.groupName = "myGroup";
    return action;
}

次の例では、ユーザーをグループから削除します。

@FunctionName("removeFromGroup")
@SignalROutput(name = "$return", HubName = "hubName1")
public SignalRGroupAction removeFromGroup(
        @HttpTrigger(
            name = "req",
            methods = { HttpMethod.POST },
            authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Object> req,
        @BindingName("userId") String userId) {

    SignalRGroupAction groupAction = new SignalRGroupAction();
    groupAction.action = "remove";
    groupAction.userId = userId;
    groupAction.groupName = "myGroup";
    return action;
}

属性

インプロセス分離ワーカー プロセスの C# ライブラリの両方で、属性を使用して関数を定義します。 C# スクリプトでは、代わりに function.json 構成ファイルを使います。

次の表では、SignalROutput 属性のプロパティについて説明します。

属性のプロパティ 説明
HubName この値は、接続情報が生成される SignalR ハブの名前に設定する必要があります。
ConnectionStringSetting SignalR Service 接続文字列を含むアプリ設定または設定コレクションの名前。既定ではAzureSignalRConnectionString

注釈

次の表では、SignalROutput 注釈でサポートされている設定について説明します。

設定 内容
name 接続情報オブジェクトの関数コードで使用される変数名。
hubName この値は、接続情報が生成される SignalR ハブの名前に設定する必要があります。
connectionStringSetting SignalR Service 接続文字列を含むアプリ設定または設定コレクションの名前。既定ではAzureSignalRConnectionString

構成

次の表は、function.json ファイルで設定したバインド構成のプロパティを説明しています。

function.json のプロパティ 説明
type signalR に設定する必要があります。
direction out に設定する必要があります。
name 接続情報オブジェクトの関数コードで使用される変数名。
hubName この値は、接続情報が生成される SignalR ハブの名前に設定する必要があります。
connectionStringSetting SignalR Service 接続文字列を含むアプリ設定または設定コレクションの名前。既定ではAzureSignalRConnectionString

ローカルで開発する場合は、Values コレクション内の local.settings.json ファイルにアプリケーション設定を追加します。

使用方法

最適なセキュリティのために、関数アプリでは、共有秘密鍵を含む接続文字列を使用する代わりに、Azure SignalR サービスに接続するときにマネージド ID を使用する必要があります。 詳細については、「 Microsoft Entra マネージド ID を使用して Azure SignalR Service リソースへの要求を認証するを参照してください。

次のステップ