2
  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.

Rahul
  • 2,431
  • 3
  • 35
  • 77
  • Could you add to your question by posting a [mcve] of the OData proxy class and your context class? – MindSwipe Jul 09 '19 at 07:04
  • "Operation is not supported on this platform" sounds like a "limitation" to me, yes... – ADyson Jul 09 '19 at 07:13
  • @MindSwipe I have added the code in my question. I have already added the steps 1-4 in the question. Odata Proxy: https://github.com/DevExpress/EF-Core-Security/wiki/How-to-create-a-client-Console-Application-for-the-OData-server-with-the-EF-Core-Security – Rahul Jul 09 '19 at 07:14
  • How did you create the OData client? Seeing HttpWebRequest in a .NET Core project is unusual. In any case, .NET Core is still a preview, Blazor even more so. The OData clients target .NET Core 2.2, which means you'll encounter incompatibilities in any case. In this case the OData library is using methods and classes that *aren't* available in Blazor. The error complains about the configured proxy server. You can probably bypass this by explicitly setting the proxy server in `MyContext` if possible. – Panagiotis Kanavos Jul 09 '19 at 07:30
  • 2
    In any case, OData is a protocol that works on top of HTTP. You don't *need* the generated proxy. If you check [Enabling Pagination in Blazor with OData](https://devblogs.microsoft.com/odata/enabling-pagination-in-blazor-with-odata/) you'll see it uses HttpClient and a URL, not an OData client, to call the OData API – Panagiotis Kanavos Jul 09 '19 at 07:38
  • A issue has been reported in the GitHub: https://github.com/OData/ODataConnectedService/issues/122 – Rahul Jun 04 '20 at 19:04
  • Using ODada Connected Service makes life easier for CSB (Client Side Blazor). However as mentioned the proxy generated works with server side blazor and for CSB it gives an error. The guys at Microsoft need to work on this to make blazor development a reality. – Amour Rashid May 10 '20 at 20:23
  • Yes, Odata Connected Service is works fine in Server Side Blazor. The issue is with the client side blazor. – Rahul Jun 04 '20 at 19:06

1 Answers1

4

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();
    }
Kubus
  • 677
  • 6
  • 18
  • 1
    This works with Microsoft.OData.Client 7.6.4. In version 7.7.0 a breaking change was introduced. – Kubus Jun 26 '20 at 20:42
  • You are right, its works with Microsoft.OData.Client 7.6.4. Tried with the with the latest 7.2.2, but Nuget version conflicts are there. – Rahul Oct 30 '20 at 06:27
  • 1
    @Rahul I edited the solution. You can use directly Microsoft.OData.Client from version 7.8.1 without adding Microsoft.OData.Extensions.Client package – Kubus Dec 29 '20 at 11:45
  • what is the use of 'Format.LoadServiceModel' and what are the benefits of it? I couldn't find any related documentation. – Rahul Feb 24 '22 at 07:19