Forum Discussion

vkeda29's avatar
vkeda29
Icon for Advocate I rankAdvocate I
10 days ago

Best practices for integrating the Fabric ML Model endpoint with an application (preferably .NET)?

Hi,

I'm working on a ML use case in Microsoft Fabric where we train models using Fabric notebooks, track experiments through MLflow, and register models for real-time predictions. We have already registered a model and activated its real-time inference endpoint in Fabric. We're now planning to integrate this endpoint with an application (preferably .NET).

I'd appreciate some guidance on the recommended integration approach, particularly around authentication, permissions, and API invocation.

A few questions:

  1. Authentication: What is the recommended way for the backend (.NET) to authenticate with a Fabric ML Model endpoint? Does it support OAuth 2.0 Client Credentials using a Microsoft Entra service principal, and is Managed Identity also supported?
  2. Permissions: What Fabric workspace or ML Model permissions are required for a service principal to invoke an activated endpoint? Are any additional tenant-level settings required?
  3. API integration: What is the recommended approach for calling the endpoint from .NET application, including the request payload format, response handling, and access-token management?
  4. Endpoint behavior: Are there any considerations around synchronous/asynchronous responses, latency, timeouts, or concurrent requests when integrating the endpoint with an application?
  5. Model versioning: If we train and register an updated model version later, can we activate a new endpoint while keeping the existing version available? What is the recommended approach for switching between versions without affecting the application?

If anyone has implemented a similar integration, I'd appreciate any recommended architecture, documentation, or working. Also would like to understand whether there is a secure Fabric-native approach that would be more appropriate.

Thanks in advance!

9 Replies

  • Hi vkeda29​ 

    For auth, check the docs. It might vary depending on the endpoint that you want to use, but in general the ML endpoints do support managed identities, service principals, and users. Endpoint - REST API (MLModel) | Microsoft Learn

    For permissions, also check the API docs, they specify which permissions are required. 
    The Activate ML Model endpoint (Endpoint - Activate ML Model Endpoint Version - REST API (MLModel) | Microsoft Learn) specifies that the caller must have write on the model. 

    Looking at the permissions table here: 
    Data science roles and permissions - Microsoft Fabric | Microsoft Learn

    That means that if access is granted through workspace roles, the caller needs to have a role of at least contributor. 

    For API integration, this varies depending on the specific endpoints you are using. THe docs have example calls for all endpoints, so that is a good place to start. 

    For async calls, yes you will need to ensure that your .net application is built to handle async calls well, as the endpoints will take some time to return depending on which endpoint you are using. 

    To test different versions, the activate endpoint call does specific an endpoint name or version, however I would recommend you test out new model versions in a different workspace in a DEV/TST version of your application, and not rely on Fabric keeping all versions available in your production environment. 

    • vkeda29's avatar
      vkeda29
      Icon for Advocate I rankAdvocate I

      Hi tayloramy​ , 
      Thanks for the explanation.

      Now, I'm currently integrating the Fabric ML Model endpoint with a .NET application and encountering a 401 Unauthorized error when calling the scoring API.

      The endpoint is activated and working as expected when tested directly through Postman. However, when the application calls the same Fabric scoring API, it returns HTTP 401.

      As far as we've verified, the same Bearer token and authentication details are being used.

      Endpoint pattern:

      POST /v1/workspaces/{workspaceId}/mlmodels/{modelId}/endpoint/score

      Error response:

      { "errorCode": "RequestFailed", "message": "Unable to process the request", "isRetriable": false }

      Additional details from the application logs:

      • HTTP status: 401 Unauthorized
      • Authorization header present on final request: True
      • WWW-Authenticate header: Empty
      • Postman request: Successful
      • Application request: Fails with 401

      The error response doesn't provide any additional information to identify the exact cause.

      I'm trying to understand whether there are any specific authentication, authorization, endpoint configuration, or HTTP client requirements when calling Fabric ML Model endpoints from an external application.

      Has anyone encountered a similar issue where the same token works in Postman but fails when used in the application?

      Are there any additional headers, permissions, redirect behaviors, or diagnostic steps that we should check to identify the cause? Any suggestions?

      Thanks!

      • tayloramy's avatar
        tayloramy
        Icon for Super User rankSuper User

        Hi vkeda29​ 

        If you're able to authenticate requests through Postman, then the endpoint is working as expected. If the same request is not authenticating through your custom .NET app, then there is something wrong with the .NET app or it is not sending the same credentials. 

        WIthout more information about your .NET app, I don't think I can provide much support. 

         

  • jubinsoni's avatar
    jubinsoni
    Icon for Memorable Member rankMemorable Member

    Hi vkeda29​,

    I'll focus on the .NET side, since that's where most of the integration effort goes. Treat the endpoint like any other Entra-protected Fabric API: get a token for the Fabric resource, call the scoring URL shown in the model's endpoint pane, and send the payload in the format of the sample request shown there.

    For the backend, use Azure.Identity so the same code works with a service principal locally/CI and a managed identity in Azure. The SPN needs the tenant setting that allows service principals to use Fabric APIs, plus access to the workspace that holds the model. Give it the least role that works in your test, and check the current docs since the endpoint feature is still evolving.

    // Program.cs
    builder.Services.AddSingleton<TokenCredential>(new DefaultAzureCredential()); // MI in Azure, SPN via env vars elsewhere
    builder.Services.AddTransient<FabricAuthHandler>();
    builder.Services.AddHttpClient<ScoringClient>(c =>
    {
        c.BaseAddress = new Uri(builder.Configuration["Fabric:ScoringUrl"]!);
        c.Timeout = TimeSpan.FromSeconds(30);
    })
    .AddHttpMessageHandler<FabricAuthHandler>()
    .AddStandardResilienceHandler(); // retries 429/5xx with backoff (Microsoft.Extensions.Http.Resilience)
    
    // FabricAuthHandler.cs - token is cached and refreshed by Azure.Identity
    public class FabricAuthHandler(TokenCredential cred) : DelegatingHandler
    {
        static readonly string[] Scope = ["https://api.fabric.microsoft.com/.default"];
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage req, CancellationToken ct)
        {
            var token = await cred.GetTokenAsync(new TokenRequestContext(Scope), ct);
            req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.Token);
            return await base.SendAsync(req, ct);
        }
    }

    For versioning, don't hardcode the version-specific URL in the app. Keep the scoring URL in configuration (App Configuration or Key Vault). Then switching versions is: activate the new version's endpoint, smoke-test it, flip the config value, and deactivate the old one after a soak period. If your endpoint pane offers a default-version URL, point the app at that instead and switch the default in Fabric.

    Also keep the endpoint call off the request path where you can. Real-time endpoints can scale down when idle, so the first call after a quiet period can be slow. A small warm-up ping on startup, plus a sensible timeout and fallback in the app, avoids user-facing hangs.

    So my overall approach would be:

    Auth -> DefaultAzureCredential (MI in Azure, SPN elsewhere), scope = Fabric API
    SPN -> tenant setting for Fabric APIs + least workspace role that works
    HttpClient -> auth handler + resilience handler (429/5xx retry) + timeout
    Scoring URL in config -> version switch = config flip, not redeploy
    Warm-up + fallback for cold endpoints

    AI-assisted drafting: AI was used to help structure and phrase this response. I reviewed and validated the technical content before posting.

  • I think one thing missing here is that scoring itself needs MLModel Write permission, even after the endpoint is active. A valid Entra token alone isn't enough.

    In .NET, 202 means the prediction isn't ready yet. Poll Location using Retry-After, then fetch the result. Handle 429 with Retry-After too. For model updates, keep the app on /endpoint/score. Test the new version through /versions/{name}/score, then change the default in Fabric. Both versions can stay active, up to five total. Just keep an eye on Fabric capacity usage.

    • vkeda29's avatar
      vkeda29
      Icon for Advocate I rankAdvocate I

      Hi Kagiyama_yutaka​ ,
      Thanks for the explanation.
      Now, I'm currently integrating the Fabric ML Model endpoint with a .NET application and encountering a 401 Unauthorized error when calling the scoring API.

      The endpoint is activated and working as expected when tested directly through Postman. However, when the application calls the same Fabric scoring API, it returns HTTP 401.

      As far as we've verified, the same Bearer token and authentication details are being used.

      Endpoint pattern:

      POST /v1/workspaces/{workspaceId}/mlmodels/{modelId}/endpoint/score

      Error response:

      { "errorCode": "RequestFailed", "message": "Unable to process the request", "isRetriable": false }

      Additional details from the application logs:

      • HTTP status: 401 Unauthorized
      • Authorization header present on final request: True
      • WWW-Authenticate header: Empty
      • Postman request: Successful
      • Application request: Fails with 401

      The error response doesn't provide any additional information to identify the exact cause.

      I'm trying to understand whether there are any specific authentication, authorization, endpoint configuration, or HTTP client requirements when calling Fabric ML Model endpoints from an external application.

      Has anyone encountered a similar issue where the same token works in Postman but fails when used in the application?

      Are there any additional headers, permissions, redirect behaviors, or diagnostic steps that we should check to identify the cause? Any suggestions?

      Thanks!

  • v-achippa's avatar
    v-achippa
    Icon for Community Support rankCommunity Support

    Hi vkeda29​,

    Thank you for reaching out to Microsoft Fabric Community.

    Thank you tayloramy​, jubinsoni​ and Kagiyama_yutaka​ for the prompt response.

    As we haven’t heard back from you, we wanted to kindly follow up to check if the solution provided by the user's for the issue worked? or let us know if you need any further assistance.

    Thanks and regards,
    Anjan Kumar Chippa

  • v-achippa's avatar
    v-achippa
    Icon for Community Support rankCommunity Support

    Hi vkeda29​,

    We wanted to kindly follow up to check if the solution provided by the user's for the issue worked? or let us know if you need any further assistance.

    Thanks and regards,
    Anjan Kumar Chippa

  • Hi vkeda29

    Same token string working in Postman but failing in the app usually means the two calls are not the same identity. Postman is probably sending a token for your own user. The app is likely running as a service principal or managed identity, and Fabric checks those differently.

    Decode both tokens at jwt.ms and compare them. The aud should be https://api.fabric.microsoft.com. A user token carries scp, an app token carries roles, and oid or appid shows who the caller really is.

    If the app token is a service principal or managed identity, check two things. First, the tenant setting Service principals can use Fabric APIs must be on, and the identity must be in the allowed group if the setting is limited to one. Second, the identity needs write on the model, which in practice means Contributor or higher on the workspace.

    I can't see your app, so I can't tell which of these it is. Does the app's token decode as a user or as an app?