Xbim IFC Viewer ASP.NET

135 views Asked by At

I successfully implemented an IFC viewer in NodeJs and am now trying to implement it in ASP.NET MVC Core 2.1

Here are my codes:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>ASP.NET test IFC Viewer</title>
</head>
<body>
    <script src="/js/index.js"></script>
    <canvas id="aaa" style="height: 500px; width: 500px; border: solid 1px red;"></canvas>

    <script>
        var viewer = new Viewer('aaa');
        viewer.on('loaded', () => {
            viewer.show(ViewType.DEFAULT);
        });
        viewer.load('/model/SampleHouse.wexbim');
        viewer.start();
    </script>

</body>
</html>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace WebApplication1
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddCors(options =>
            {
                options.AddPolicy("AllowAnyOrigin", builder =>
                {
                    builder.AllowAnyOrigin()
                           .AllowAnyMethod()
                           .AllowAnyHeader();
                });
            });


            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();
            app.UseCors("AllowAnyOrigin");

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

In my root directory I execute from the command prompt:

npm install @xbim/viewer

I add the index.js file from the node_modules folder to the wwwroot/js folder

I then add a folder named model in wwwroot folder In this folder I add the SampleHouse.wexbim file that I retrieved from the Xbim GitHub.

When I run my application and go to developer tools in network. I have a 404 error for the request https://localhost:44365/model/SampleHouse.wexbim

In the debugging tool I see this message below the 404 error: Failed to fetch binary data from server. Server code: 404. This might be due to CORS policy of your browser if you run this as a local file.

Message Error

Do you know how to resolve the problem?

Maybe I'm not going about it the right way to integrate an IFC Viewer into an ASP.NET application and I need to use a completely different approach using C#. Don't hesitate to tell me.

  • I tried to modify StartUp.cs to add CORS allowance.
  • I tried to pay attention to the nomenclature of paths and file names.
  • I tried to solve the problem with ChatGpt.
  • I tried restarting my IIS Express server.
  • I checked the access permissions to the wwwroot/model folder
2

There are 2 answers

0
gbjbaanb On BEST ANSWER

Browsers are implementing the CORS requests for local files in a very strict manner - they should be requiring files to be from the same domain, but the spec says https so the implementation required http even if the entire domain is file based local files.

Here, I think you should access the files using http/https requests without using a local file (as I believe you might be loading the wexbim file directly in your js rather than accessing it via a remote call because it uses a relative path and not a http one).

But you can test this by editing your browser settings to allow such XHR permissions. On Firefox (screw Chrome) you set [privacy.file_unique_origin][1] to false in about:config. This ignores the security of loading files from a different origin (even if they are all local) and if your code starts working, then you know you are loading a local version and can fix the problem.

3
Nzeh On

The problem was related to CORS restrictions on local files. To get around the problem I defined a custom root /files/FILE_NAME in the Configure method:

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "files",
        template: "files/{fileName}",
        defaults: new { controller = "Home", action = "GetFile" }
    );

    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}"
    );
}); 

This configuration allows the application to recognize URLs containing /files/FILE_NAME as intended for special processing.

I've added a method to HomeController.cs that returns the contents of the file located in wwwroot/model to the client. :

public IActionResult GetFile(string fileName)
{
    // Chemin complet du fichier
    string filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "model", fileName);

    if (System.IO.File.Exists(filePath))
    {
        // Lire le fichier et le retourner
        var fileBytes = System.IO.File.ReadAllBytes(filePath);
        return File(fileBytes, "application/octet-stream", fileName);
    }

    return NotFound();
}   

The file can then be accessed via the /files/FILE_NAME root. I modified the Path in index.cshtml :

viewer.load('/files/SampleHouse.wexbim');

PS: I am on Mozilla. No need to set privacy.file_unique_origin to false.