2

I am trying to build an image uploader in a .NET 6 Minimal API. I believe that i have all the proper components but I am utterly confused on the problem that I am having. One specific line in the code has a CS8602 error stopping me from running the code.

app.MapPost("/submit-form", async (HttpContext context) =>
{
    var form = await context.Request.ReadFormAsync();
    var title = form["imageTitle"];
    var file = form.Files["imageFile"];

    // Perform validation checks
    if (string.IsNullOrEmpty(title))
    {
        context.Response.StatusCode = 400; // Bad Request
        await context.Response.WriteAsync("Image title is required.");
        return;
    }

    if (file == null || file.Length == 0)
    {
        context.Response.StatusCode = 400; // Bad Request
        await context.Response.WriteAsync("No image file uploaded.");
        return;
    }

    var allowedExtensions = new[] { ".jpeg", ".jpg", ".png", ".gif" };
    var fileExtension = Path.GetExtension(file.FileName);

    if (!allowedExtensions.Contains(fileExtension.ToLower()))
    {
        context.Response.StatusCode = 400; // Bad Request
        await context.Response.WriteAsync("Invalid file format. Accepted formats: JPEG, PNG, GIF.");
        return;
    }

    // If validation passes, continue with further actions
    // Generate unique ID for the image
    var imageId = Guid.NewGuid().ToString();

    // Store image information
    var imageInfo = new
    {
        ImageId = imageId,
        Title = title,
        file.FileName
    };

    // Serialize image information to JSON
    var json = JsonSerializer.Serialize(imageInfo);

    // Store JSON data in a file on disk
    var filePath = Path.Combine(Directory.GetCurrentDirectory(), "images", $"{imageId}.json");
    await File.WriteAllTextAsync(filePath, json);

    // Redirect to the page with the unique ID
    var redirectUrl = $"/picture/{imageId}";
    context.Response.Redirect(redirectUrl);
});

That is the first MapPost code block.

app.MapGet("/picture/{id}", async (HttpContext context) =>
{
    var imageId = context.Request.RouteValues["id"] as string;
    var filePath = Path.Combine(Directory.GetCurrentDirectory(), "images", $"{imageId}.json");

    if (!File.Exists(filePath))
    {
        context.Response.StatusCode = 404; // Not Found
        await context.Response.WriteAsync("Image not found.");
        return;
    }

    // Read the JSON data from the file
    var json = await File.ReadAllTextAsync(filePath);

    // Deserialize the JSON data to retrieve the image information
    var imageInfo = JsonSerializer.Deserialize<Dictionary<string, object>>(json);

    // Get the title from imageInfo dictionary
    string title;
    if (imageInfo.TryGetValue("Title", out var titleObj) && titleObj is string)
    {
        title = (string)titleObj;
    }
    else
    {
        title = string.Empty;
    }

    // Get the file name from imageInfo dictionary
    string fileName;
    if (imageInfo.TryGetValue("FileName", out var fileNameObj) && fileNameObj is string)
    {
        fileName = (string)fileNameObj;
    }
    else
    {
        fileName = string.Empty;
    }

    // Render a page that displays the image title and the image itself
    await context.Response.WriteAsync($"<h1>{title}</h1>");
    await context.Response.WriteAsync($"<img src=\"/images/{imageInfo["FileName"]}\" alt=\"{title}\">");
});

app.Run();

The error is happening just above the bottom of the code. in the second if statement,

if (imageInfo.TryGetValue("Title", out var titleObj) && titleObj is string)
    {
        title = (string)titleObj;
    }
    else
    {
        title = string.Empty;
    }

imageInfo is creating the error is dereference of a possibly null reference

8
  • 1
    we are not a compiler so we don't know all the errors and warning a compiler or whatever tool may throw. Can you please provide the exact message also? Commented Jun 29, 2023 at 17:50
  • oh youre right i am sorry. dereference of a possibly null reference Commented Jun 29, 2023 at 17:52
  • Well, apparently JsonSerializer.DeSerialize returns object?, so chances are you get a null. The warning just informs you that you should check for that before using the variable. If you know for sure that Deserialize allways returns an object, than you may ignore about that warning and use imageInfo!.TryGetValue, which is the null-forgiving operator Commented Jun 29, 2023 at 17:53
  • Yeah, I simply dont know how to fix it and its giving me a compile time error and not running the build Commented Jun 29, 2023 at 17:55
  • Something like if(imageInfo != null && <rest of the condition>)? Commented Jun 29, 2023 at 17:56

1 Answer 1

0

There is a feature called Nullable reference types which is enabled by default in the "new" application templates. It enables ability for compiler to perform nullable state static flow analysis (during compilation) which should reduce a possibility of "The Billion Dollar Mistake". Also it seems that your application has either TreatWarningsAsErrors or (more likely) corresponding warnings specifically because by default this analysis produces warnings, not errors. You need to perform null checks in the ifs:

string title;
if (imageInfo != null && imageInfo.TryGetValue("Title", out var titleObj) && titleObj is string)
{
    title = (string)titleObj;
}
else
{
    title = string.Empty;
}

string fileName;
if (imageInfo != null && imageInfo.TryGetValue("FileName", out var fileNameObj) && fileNameObj is string)
{
    fileName = (string)fileNameObj;
}
else
{
    fileName = string.Empty;
}

And then fix the write statement to actually use fileName (I suppose that was the original intent here):

await context.Response.WriteAsync($"<img src=\"/images/{fileName}\" alt=\"{title}\">");

Personally I would assign the empty value from the start and then used pattern matching to simplify the code:

var title = string.Empty;
if (imageInfo != null && imageInfo.TryGetValue("Title", out var titleObj) && titleObj is string value)
{
    title = value;
}

var fileName = string.Empty;
if (imageInfo != null && imageInfo.TryGetValue("FileName", out var fileNameObj) && fileNameObj is string obj)
{
    fileName = obj;
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.