Um botão de operação executa uma operação registrada pelo servidor — uma API personalizada, uma ação personalizada, uma mensagem própria do Dataverse ou código seu — e aparece apenas para os usuários para os quais está registrado. O botão pergunta ao servidor uma vez quais operações o usuário logado pode executar, e verifica cada registro que enviaria em relação ao que o usuário pode fazer com ele, para não oferecer o que o servidor recusaria. O servidor ainda julga cada solicitação quando ela é enviada.
Registre uma operação no servidor Program.cs: AddOperationAccess para uma operação do Dataverse, AddOperationHandler para seu próprio código. Dentro AddPortalRolede , WithOperationAccess e WithOperationHandler conceda uma aos detentores do papel. Um registro indica quem pode executar a operação, os parâmetros que uma solicitação pode carregar, os registros para os quais devem apontar e as saÃdas que retornam.
// Program.cs (the server)
// Uma API personalizada para os portadores do papel de Faturamento, em uma fatura eles podem ser alterados
builder.Services.AddPortalRole("Billing", role => role
.WithOperationAccess("ppp_IssueRefund", o => o
.OnRecord("Target", TableSecurityPermission.Write)
.AcceptingParameters("Amount")
.ReturningOutputs("RefundId")));
// Seu próprio código, para qualquer usuário logado, em uma cotação que ele possa ler
builder.Services.AddOperationHandler<SendQuoteHandler>("SendQuote", o => o
.ForSignedInUsers()
.OnRecord("Quote", TableSecurityPermission.Read)
.ReturningOutputs("SentTo"));
public sealed class SendQuoteHandler(IQuoteMailer mailer) : IPortalOperationHandler
{
public async Task<IReadOnlyDictionary<string, ColumnValueBase?>?> ExecuteAsync(
PortalOperationContext context, CancellationToken cancellationToken)
{
var quote = context.GetParameter<LookupValue>("Quote")!;
var sentTo = await mailer.SendAsync(quote.Value!.Value, cancellationToken);
return new Dictionary<string, ColumnValueBase?> { ["SentTo"] = new StringValue { Value = sentTo } };
}
}
ForEveryone(), ForSignedInUsers(), ForContactsMatching(fetchXml) e ForWebRoles(...) digam quem pode executá-la; o registro de uma função é para os detentores da função. Sob a segurança nativa do Dataverse, os contatos possuem papéis web em vez de portais, e uma API personalizada é oferecida apenas a usuários cujos papéis de segurança concedem seu privilégio de execução.Coloque onde OperationButton a operação pertence, nomeando a operação e o parâmetro em que seu registro vai entrar.
<RecordContext table="invoice" queryParameterName="id">
<OperationButton
operation="ppp_IssueRefund"
recordParameter="Target"
label="Issue refund"
icon={<Money20Regular />}
confirmationMessage="Issue a refund for this invoice?"
getParameters={askForAmount}
onCompleted={({ outputs }) => showRefund(outputs.RefundId)}
/>
</RecordContext><RecordContext TableName="invoice" QueryParameterName="id">
<OperationButton Operation="ppp_IssueRefund"
RecordParameter="Target"
Label="Issue refund"
Icon="@(new Icons.Regular.Size20.Money())"
ConfirmationMessage="Issue a refund for this invoice?"
GetParametersAsync="AskForAmountAsync"
OnCompleted="ShowRefund" />
</RecordContext>WhenNotAllowed (whenNotAllowed) para desativá-la em vez disso. A resposta é pedida uma vez e mantida enquanto o aplicativo está aberto; uma solicitação que o servidor recusa pede novamente.RecordParameterem : Record, qualquer registro por referência, ou então o registro do RecordContext botão fica lá, uma vez salvo. O usuário deve poder agir conforme o registro exige: o registro de um formulário diz o que o usuário pode fazer com ele, e um registro nomeado por referência é lido para ele.Parameters são enviadas com cada requisição, e GetParametersAsync (getParameters) acumula mais quando o botão é clicado, por exemplo; não devolver nada cancela o clique. ConfirmationMessage pergunta antes da operação rodar e OnCompleted devolve suas saÃdas.Label ou seu conteúdo, e seu Ãcone, dica de ferramenta e aparência como em qualquer outro botão.A demo registra algumas linhas de seu próprio código como uma operação para todos. Digite um nome e clique no botão: o servidor responde, e a página diz a saudação.
Na barra de ferramentas de uma grade, OperationGridButton executa a operação uma vez para cada linha selecionada, enviando a linha em RecordParameter, e então atualiza a grade. Ela é ativada enquanto cada linha selecionada é uma que o usuário pode agir, que cada linha diz por si só. As requisições de uma operação do Dataverse são enviadas em uma única transação, então todas são executadas ou nenhuma roda; seu próprio código roda em uma linha de cada vez e para na primeira que falha.
<MainGrid tableName="invoice">
<GridToolbarItems>
<OperationGridButton
operation="ppp_ApproveInvoice"
recordParameter="Target"
label="Approve"
whenNotAllowed="disable"
/>
</GridToolbarItems>
</MainGrid><MainGrid TableName="invoice">
<ToolbarItems>
<OperationGridButton Operation="ppp_ApproveInvoice"
RecordParameter="Target"
Label="Approve"
WhenNotAllowed="OperationButtonBehavior.Disable" />
</ToolbarItems>
</MainGrid>Selecione algumas contas e clique em Verificar: o próprio código da demo lê cada uma e responde seu nome. Aprovar é concedido apenas para um papel de portal que nenhum visitante possui, então aparece como desativado.
Nome da Conta
Nome da Conta Digite o nome da empresa ou do negócio. | Número da Conta Número da Conta Digite um número de ID ou código para a conta para pesquisar e identificar rapidamente a conta nas visualizações do sistema. | Telefone Principal Telefone Principal Digite o número principal dessa conta. | Endereço 1: Cidade Endereço 1: Cidade Digite a cidade como endereço principal. | Receita Anual Receita Anual Digite a receita anual da conta, usada como indicador na análise de desempenho financeiro. | Contato Primário Contato Primário Escolha o contato principal da conta para fornecer acesso rápido aos dados de contato. | |
|---|---|---|---|---|---|---|
| Abernathy - MacGyver | KTWSLQHY | (491) 600-8029 | Tampa | $15.959.059,84 | Bradford Kiehn | |
| Abshire - Marks | 4EBO9F42 | (432) 879-3107 | Boston | $14.635.260,82 | Archibald Bailey | |
| Adams - Torphy | K6VNNUCN | (864) 842-2566 | Annapolis | $4.567.299,55 | Merle Vandervort | |
| Altenwerth, D'Amore and Mante | F9MN5BAZ | (125) 048-0015 | Gulfport | $3.839.082,81 | Heidi Reichel | |
| Ankunding and Sons | 92P2G0SF | (603) 147-5429 | Fargo | $32.724.448,89 | Fatima White | |
| Balistreri, Heller and Murphy | 3Y0AF481 | (909) 808-9886 | New Haven | $7.097.756,35 | Angie Kreiger | |
| Balistreri, Steuber and Schultz | FF5RCGXG | (435) 761-0052 | Hattiesburg | $35.943.517,75 | Jake Bogisich | |
| Bartoletti LLC | JBQ0L2O8 | (292) 573-7498 | Santa Fe | $766.813,66 | Cecil Sipes | |
| Bartoletti, Ratke and Beatty | WZIDG7K2 | (267) 075-5978 | Portland | $32.338.459,84 | Tabitha Morissette | |
| Barton, Koepp and Cronin | TGAL5Y8F | (821) 885-8434 | Norman | $43.550.293,98 | Marc Dibbert | |
| Bashirian - Hamill | ZS1XZLDL | (792) 135-0145 | Baltimore | $15.916.182,51 | Alexie Dach | |
| Bashirian - Weber | OC5PYOJC | (492) 789-5504 | Cranston | $23.269.960,31 | Emmet Krajcik | |
| Baumbach and Sons | X8V8TZRX | (670) 937-4364 | Ann Arbor | $4.319.879,33 | Charity Sawayn | |
| Baumbach, Maggio and Turner | V24ZA492 | (509) 251-9848 | Orlando | $25.479.745,81 | Cali McClure | |
| Beahan Inc | B9XXSIJM | (262) 429-4179 | Sioux Falls | $45.854.197,84 | Tressa Graham | |
| Berge and Sons | WO8OIGR6 | (165) 108-8947 | Topeka | $40.560.550,52 | Delphine Jerde | |
| Bergnaum Group | T3KB03RE | (381) 148-7032 | Rapid City | $32.406.150,23 | Dakota Ward | |
| Bergstrom and Sons | G99XNRDY | (182) 902-0206 | Casper | $48.880.601,83 | Grant Funk | |
| Bergstrom, Bins and Flatley | J1TXPJ9I | (409) 160-0657 | Pittsburgh | $21.005.421,54 | Blanche Gulgowski | |
| Blanda - Terry | 4L8RSVL9 | (190) 468-0033 | Vancouver | $33.567.160,56 | Fausto Pagac | |
| Bode LLC | F5IR66HK | (386) 496-6921 | Detroit | $1.800.033,15 | Kane Pollich | |
| Bogisich, Mitchell and Balistreri | PCVDL8PS | (267) 567-6606 | Manchester | $10.336.491,66 | Esperanza Luettgen | |
| Borer - Mohr | LHI1SSVO | (070) 539-8404 | Providence | $36.092.236,14 | Emelia Murray | |
| Botsford - Baumbach | 8JZK18K6 | (389) 188-6100 | Cranston | $318.662,34 | Maria Runte | |
| Botsford, Schroeder and Kassulke | U39NNCOJ | (960) 101-3753 | Sacramento | $19.016.940,28 | Raphael Bergnaum | |
| Boyer - Schaefer | EFJQXML0 | (473) 115-3249 | Fort Wayne | $48.601.111,30 | Moses Metz | |
| Boyle, Zulauf and Lakin | XXRF6GXU | (028) 071-4090 | Helena | $31.856.728,91 | Federico Hamill | |
| Brekke LLC | UCLPTB19 | (795) 385-0349 | Norman | $25.296.518,98 | Noemie Stracke | |
| Brekke, Feeney and Johns | VMGNL1M7 | (203) 861-9656 | Charleston | $13.632.447,58 | Kristin Koch | |
| Brown, Rohan and Mayer | EMOSYGOI | (479) 235-6497 | Fairbanks | $49.780.735,02 | Phoebe Legros | |
| Cassin, Kassulke and Schaefer | 5KSSVNW7 | (852) 978-3789 | Flagstaff | $29.260.487,45 | Dedrick Thiel | |
| Christiansen - Metz | GSZJ1ODJ | (183) 163-4723 | Reno | $25.227.451,85 | Hattie Schuster | |
| Cole, Tillman and Langworth | Y1JNB47Q | (289) 893-2488 | Dover | $13.838.171,56 | Jody Rohan | |
| Connelly, Cassin and Ledner | 69QI6R89 | (507) 196-5103 | Wilmington | $28.880.982,86 | Berneice Stracke | |
| Considine Inc | 1ZGMEMAV | (013) 094-8065 | Anchorage | $6.796.633,66 | Guido Hagenes | |
| Considine, Wilkinson and Spencer | HK18ZLOO | (772) 222-6147 | Jersey City | $8.490.647,93 | Douglas Prosacco | |
| Cormier - Hettinger | JFLKC0CK | (508) 849-8368 | Tucson | $14.771.052,63 | Nola Hand | |
| Cremin - Hodkiewicz | 4D30N08W | (757) 968-3487 | Fort Wayne | $27.239.848,21 | America Harber | |
| Cruickshank - Pollich | P3JT5LVY | (048) 698-7364 | Santa Fe | $32.195.480,36 | Joey Reilly | |
| Cruickshank, Auer and Schoen | TV06VSEA | (516) 585-5831 | Sioux Falls | $3.560.781,82 | Tiana Kiehn | |
| Cummerata Group | AJYD1N4I | (429) 577-7392 | Minneapolis | $20.579.317,84 | Gustave Zboncak | |
| Daniel LLC | ADF0WMN9 | (371) 118-7804 | Madison | $49.497.674,02 | Francisco Smitham | |
| Denesik, Skiles and Beier | 2ZMSATDW | (716) 332-8853 | Louisville | $25.958.417,48 | Dock Aufderhar | |
| Dibbert LLC | 4WT0EDV0 | (343) 448-8435 | Huntington | $24.379.660,89 | Elroy Leuschke | |
| Dickinson Inc | C7SI8E20 | (429) 201-5173 | Dover | $44.819.510,87 | Milton Ledner | |
| Dietrich and Sons | LAEDD52L | (189) 560-2423 | Hartford | $3.522.175,29 | Heath Kunde | |
| Donnelly - Sanford | 8SW26RNC | (738) 522-0182 | Fort Wayne | $37.819.037,93 | Betsy King | |
| Dooley - Nitzsche | NUCMFF7S | (574) 958-0441 | Charleston | $11.318.528,04 | Roman Dietrich | |
| Durgan and Sons | CKOSAHML | (332) 942-8325 | Saint Paul | $5.901.769,33 | Connor Marks | |
| Ebert - Wyman | HJBQWXIR | (753) 557-3136 | Los Angeles | $15.782.605,89 | Zetta Nolan |
Os botões perguntam GET /api/permissions/operations, o que responde apenas para o usuário logado: cada operação que ele pode executar, ou apenas aquelas que você nomeia, com o que uma solicitação para cada uma pode conter e os registros para os quais deve apontar. Sua própria interface pode pedir o mesmo através IOperationAccessCache ou IPowerPortalsProService.GetOperationAccessForCurrentUserAsync no Blazor, e useOperationAccess /ou ppp.retrieveOperationAccessAsync no React.