Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asp.Net Core API CORS policy error only in file upload

I have CORS Policy blocking error only while uploading file to server using AspNet Core API 3.1. Adding cors policy to startup in different ways and using custom middleware not solved my problem.

Startup:

// ConfigureServices

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

// Configure

    app.UseCors("EnableSVCCors");

All API methods working fine by calling from react client web site but while trying to upload image I have following error:

Access to XMLHttpRequest at 'http://172.16.1.34:1980/api/accounts/uploadAvatar' from origin 'http://172.16.1.35:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

I also try to change cors policy as below but not working:

    services.AddCors(options =>
    {
        options.AddPolicy("EnableSVCCors", builder =>
        {
            builder
                .WithOrigins("http://172.16.1.35:3000")
                .AllowAnyHeader()
                .AllowAnyMethod()
                .Build();
        });
    });

Note: Calling http://172.16.1.34:1980/api/accounts/uploadAvatar using PostMan and sending base64 string as image is working fine! So there is no problem with access limits on folder where image going to be saved.

I also tried to add custom middleware as below but not working as yet:

    public class CorsMiddleWare
    {
        private readonly RequestDelegate _next;

        public CorsMiddleWare(RequestDelegate next)
        {
            _next = next;
        }

    public Task Invoke(HttpContext httpContext)
    {
        httpContext.Response.Headers.Add("Access-Control-Allow-Origin", "http://172.16.1.35:3000");

        return _next(httpContext);
    }
}

public static class CorsMiddlewareExtensions
{
    public static IApplicationBuilder UseCorsMiddleware(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<CorsMiddleWare>();
    }
}

Any one have any idea please?

EDIT : Return headers in console is as below

Request URL: http://172.16.1.34:1980/api/accounts/uploadAvatar Referrer Policy: no-referrer-when-downgrade Date: Tue, 14 Apr 2020 03:50:49 GMT Server: Microsoft-IIS/10.0 Transfer-Encoding: chunked X-Powered-By: ASP.NET Accept: application/json, text/plain, / Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9 Authorization: Bearer eyJhb..... Connection: keep-alive Content-Length: 22869 Content-Type: application/json;charset=UTF-8 Host: 172.16.1.34:1980 Origin: http://172.16.1.35:3000 Referer: http://172.16.1.35:3000/create-profile User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36 {fileName: "avatar", mediaType: "image/png",…} fileName: "avatar" mediaType: "image/png" buffer: "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6CAYAAACI7Fo9AAAgAE

like image 477
Mehdi Avatar asked Jan 20 '26 04:01

Mehdi


1 Answers

The problem solved by changing the type of object is sending as image file to HttpFile contains in MultipartDataMediaFormatter.V2 https://github.com/iLexDev/ASP.NET-WebApi-MultipartDataMediaFormatter

Upload View Model :

public class ProfileAvatarUploadViewModel
{
    public HttpFile Image { get; set; }
}

Api Controller :

[HttpPost("UploadAvatar")]
[Authorize(AuthenticationSchemes = "Bearer", Roles = "Manager,Admin,User")]
public async Task<IActionResult> UploadAvatar([FromBody] ProfileAvatarUploadViewModel model)
{
    var userId = User.FindFirst(ClaimTypes.Name)?.Value;

    if (userId == null || !await _userAccountRepository.IsExists(int.Parse(userId)))
    {
        return Forbid();
    }

    var avatarToUpload = new ProfileAvatarUploadModel
    {
        UserAccountId = int.Parse(userId),
        UploadedImage = model.Image
    };

    var uploadedAvatar = await _profileAvatarRepository.UploadAvatar(avatarToUpload);

    return Ok(uploadedAvatar);
}

Repository :

public async Task<ProfileAvatarViewModel> UploadAvatar(ProfileAvatarUploadModel model)
{
    var (key, value) = SVCardTools.SaveImage(model.UploadedImage);

    if (key.Equals(false))
    {
        throw new Exception(value);
    }

    var newAvatar = new ProfileAvatar
    {
        UserAccountId = model.UserAccountId,
        AvatarUrl = value,
        IsActive = false,
        IsPublic = false
    };

    _context.Entry(newAvatar).State = EntityState.Added;

    await _context.SaveChangesAsync();

    return ProfileAvatarViewModel.Set(newAvatar);
}

SaveImage function :

    public static KeyValuePair<bool, string> SaveImage(HttpFile file)
    {
        var bytes = file.Buffer;

        try
        {
            var fileExt = file.MediaType.Split('/')[1];
            switch (fileExt.ToLower())
            {
                case "png":
                    fileExt = ".png";
                    break;
                case "jpg":
                    fileExt = ".jpg";
                    break;
                default:
                    return new KeyValuePair<bool, string>(false, "Message");
            }

            var sb = new StringBuilder();
            sb.Append(DateTime.Now.Ticks);

            var saveFilePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot\\avatars",
                $"{sb}{fileExt}");

            var saveDbPath = $"{sb}{fileExt}";

            if (bytes.Length > 0)
            {
                using (var stream = new FileStream(saveFilePath, FileMode.Create))
                {
                    stream.Write(bytes, 0, bytes.Length);
                }
            }

            return new KeyValuePair<bool, string>(true, saveDbPath);

        }
        catch (Exception e)
        {
            var message = e.Message;
            return new KeyValuePair<bool, string>(false, message);
        }
    }
like image 196
Mehdi Avatar answered Jan 21 '26 20:01

Mehdi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!