odatablazorblazor-client-sideodata-connected-service

Consuming OData in Blazor Client App using OData Connected Services


  1. Created a netstandard2.1 blazor web assembly project.
  2. Added Odata Connected Service (V.0.10.0) to the same project.
  3. Generated the OData proxy class.
  4. Called the odata service from Task OnInitializedAsync() method from Razor page

Calling OData service from Razor page:

protected override async Task OnInitializedAsync()
{
    await base.OnInitializedAsync();
    var context = new Container(new Uri("http://localhost/odata"));
    var result = await context.Students.ExecuteAsync();
}

Exception from the browser:

blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: Operation is not supported on this platform.
System.PlatformNotSupportedException: Operation is not supported on this platform.
  at System.Net.WebProxy.CreateDefaultProxy () <0x35560a0 + 0x00008> in <filename unknown>:0 
  at System.Net.Configuration.DefaultProxySectionInternal.GetSystemWebProxy () <0x3555f80 + 0x00000> in <filename unknown>:0 
  at System.Net.Configuration.DefaultProxySectionInternal.GetDefaultProxy_UsingOldMonoCode () <0x3555ed8 + 0x00000> in <filename unknown>:0 
  at System.Net.Configuration.DefaultProxySectionInternal.GetSection () <0x3555cd8 + 0x0002a> in <filename unknown>:0 
  at System.Net.WebRequest.get_InternalDefaultWebProxy () <0x3555a20 + 0x00034> in <filename unknown>:0 
  at System.Net.HttpWebRequest..ctor (System.Uri uri) <0x3555460 + 0x000b6> in <filename unknown>:0 
  at System.Net.HttpRequestCreator.Create (System.Uri uri) <0x3554aa0 + 0x00004> in <filename unknown>:0 
  at System.Net.WebRequest.Create (System.Uri requestUri, System.Boolean useUriBase) <0x354cfd8 + 0x00116> in <filename unknown>:0 
  at System.Net.WebRequest.Create (System.Uri requestUri) <0x354cc00 + 0x00024> in <filename unknown>:0 
  at Microsoft.OData.Client.HttpWebRequestMessage.CreateRequest (System.String method, System.Uri requestUrl, Microsoft.OData.Client.DataServiceClientRequestMessageArgs args) <0x353fd18 + 0x00006> in <filename unknown>:0 
  at Microsoft.OData.Client.HttpWebRequestMessage..ctor (Microsoft.OData.Client.DataServiceClientRequestMessageArgs args) <0x353f750 + 0x0006e> in <filename unknown>:0 
  at Microsoft.OData.Client.RequestInfo.CreateRequestMessage (Microsoft.OData.Client.BuildingRequestEventArgs requestMessageArgs) <0x353a6d0 + 0x0016a> in <filename unknown>:0 
  at Microsoft.OData.Client.ODataRequestMessageWrapper.CreateRequestMessageWrapper (Microsoft.OData.Client.BuildingRequestEventArgs requestMessageArgs, Microsoft.OData.Client.RequestInfo requestInfo) <0x353a0b0 + 0x0000e> in <filename unknown>:0 
  at Microsoft.OData.Client.ODataMessageWritingHelper.CreateRequestMessage (Microsoft.OData.Client.BuildingRequestEventArgs requestMessageArgs) <0x3539d68 + 0x0000a> in <filename unknown>:0 
  at Microsoft.OData.Client.DataServiceRequest.CreateExecuteResult (System.Object source, Microsoft.OData.Client.DataServiceContext context, System.AsyncCallback callback, System.Object state, System.String method) <0x3511280 + 0x00192> in <filename unknown>:0 
  at Microsoft.OData.Client.DataServiceRequest.BeginExecute (System.Object source, Microsoft.OData.Client.DataServiceContext context, System.AsyncCallback callback, System.Object state, System.String method) <0x3507818 + 0x00018> in <filename unknown>:0 
  at Microsoft.OData.Client.DataServiceQuery`1[TElement].BeginExecute (System.AsyncCallback callback, System.Object state) <0x3507610 + 0x0005a> in <filename unknown>:0 
  at System.Threading.Tasks.TaskFactory`1[TResult].FromAsyncImpl (System.Func`3[T1,T2,TResult] beginMethod, System.Func`2[T,TResult] endFunction, System.Action`1[T] endAction, System.Object state, System.Threading.Tasks.TaskCreationOptions creationOptions) <0x3506d10 + 0x00188> in <filename unknown>:0 
  at System.Threading.Tasks.TaskFactory`1[TResult].FromAsync (System.Func`3[T1,T2,TResult] beginMethod, System.Func`2[T,TResult] endMethod, System.Object state) <0x34fd5f8 + 0x00014> in <filename unknown>:0 
  at Microsoft.OData.Client.DataServiceQuery`1[TElement].ExecuteAsync () <0x34fce38 + 0x00028> in <filename unknown>:0 
  at BlazorClientApp2.Pages.Index.OnInitializedAsync () [0x00094] in ..\Pages\Index.razor:12 
  at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync () <0x2ec1cd8 + 0x0013a> in <filename unknown>:0

How to overcome this issue? The main reason for using Odata Connected Service to use the property tracking feature of it.


Solution

  • Microsoft.OData.Client 7.8.1:

    Working sample

    //Program.cs Main
    var httpClient = new HttpClient {BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)};
    
    builder.Services.AddScoped(sp => httpClient);
    

    Set HttpRequestTransportMode to HttpRequestTransportMode.HttpClient in ODataServiceContext:

      public class ODataServiceContext : DataServiceContext
      {
        public ODataServiceContext(Uri serviceRoot, HttpClient httpClient)
          : base(serviceRoot, ODataProtocolVersion.V4)
        {
          if(httpClient != null)
            HttpRequestTransportMode = HttpRequestTransportMode.HttpClient; 
          
          if (EdmModel == null)
          {
            switch (HttpRequestTransportMode)
            {
              case HttpRequestTransportMode.HttpClient: 
                Format.LoadServiceModel = () => GetServiceModelAsync(httpClient).Result;
                break;
              case HttpRequestTransportMode.HttpWebRequest: 
                Format.LoadServiceModel = () => GetServiceModel(GetMetadataUri());
                break;
            }
            
            Format.UseJson();
          }
          else
          {
            Format.UseJson(EdmModel);
          }
        }
        
        public static IEdmModel EdmModel { get; set; }
    
        //WASM support
        public static async Task<IEdmModel> GetServiceModelAsync(HttpClient httpClient)
        {
          using (var stream = await httpClient.GetStreamAsync("$metadata"))
          using (var reader = XmlReader.Create(stream))
          {
            return EdmModel = CsdlReader.Parse(reader);
          }
        }
    
        public IEdmModel GetServiceModel(Uri metadataUri)
        {
          var request = WebRequest.CreateHttp(metadataUri);
    
          using (var response = request.GetResponse())
          using (var stream = response.GetResponseStream())
          using (var reader = XmlReader.Create(stream))
          {
            return CsdlReader.Parse(reader);
          }
        }
    
        private DataServiceQuery<Student> student;
    
        public DataServiceQuery<Student> Students => student = student ?? CreateQuery<Student>("Students");
      }
    
    //Blazor Wasm Component
    using System.Net.HttpClient;
    
    [Inject]
    public HttpClient HttpClient { get; set; }
    
    [Inject]
    public NavigationManager NavigationManager { get; set; }
    
        protected override async Task OnInitializedAsync()
        {
          await base.OnInitializedAsync();
    
          Uri serviceRoot = NavigationManager.ToAbsoluteUri("/odata"); //new Uri("http://localhost/odata")
    
          var dataServiceContext =
            new ODataServiceContext(serviceRoot, HttpClient);
    
          var result = await dataServiceContext.Students.ExecuteAsync();
        }
    

    Microsoft.OData.Client 7.6.4 (< 7.7.x):

    With this package Microsoft.OData.Extensions.Client you will be able to intercept dataServiceContext.Configurations.RequestPipeline.OnMessageCreating :

    //Program.cs Main
    var httpClient = new HttpClient {BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)};
    
    builder.Services.AddTransient(sp => httpClient);
    
    builder.Services.AddODataClient().AddHttpClient(httpClient);
    
    //Blazor Wasm Component
    
    using Microsoft.OData.Extensions.Client;
    
    [Inject]
    public IODataClientFactory ClientFactory { get; set; }
        
    [Inject]
    public NavigationManager NavigationManager { get; set; }
    
        protected override async Task OnInitializedAsync()
        {
          await base.OnInitializedAsync();
    
          Uri serviceRoot = NavigationManager.ToAbsoluteUri("/odata"); //new Uri("http://localhost/odata")
    
          var dataServiceContext =
            ClientFactory.CreateClient<ODataServiceContext>(serviceRoot);
    
          var result = await dataServiceContext.Students.ExecuteAsync();
        }