0

I hope someone can explain what is happening.

I created a repository class "InvoicesRepository.cs" that manage all the logic of listing, inserting, updating, deleting, etc. "Invoice.cs" objects. Is cleaner and easier to maintain.

public class InvoicesRepository
{
    protected MySQLContext db;

    public InvoicesRepository(MySQLContext db)
    {
        this.db = db;
    }

    public async void Insert(Invoice obj)
    {
        this.db.Invoices.Add(obj);
        await this.db.SaveChangesAsync();

        // performing other tasks...
    }

    // other useful methods...
}

There is a "InvoicesController.cs" with all the actions that i require. Inside this controller i create a "InvoiceTepository" obj and then use it to save information to the database. And, in every action

public class InvoicesController : Controller
{
    private InvoicesRepository invoices;

    public InvoicesController()
    {
        this.invoices = new InvoicesRepository(new MySQLContext());
    }

    [HttpPost]
    public async Task<ActionResult> Upload(Invoice invoice)
    {
        try
        {
            this.invoices.Insert(invoice);
        }
        catch (DbEntityValidationException ex)
        {
            foreach (var eve in ex.EntityValidationErrors)
            {
                foreach (var err in eve.ValidationErrors)
                {
                    ModelState.AddModelError(err.PropertyName, err.ErrorMessage);
                }
            }
        }
        catch (System.Data.Entity.Infrastructure.DbUpdateException ex)
        {
            ModelState.AddModelError("", ex.ToString());
        }
        catch (System.Data.Entity.Core.UpdateException ex)
        {
            ModelState.AddModelError("", ex.ToString());
        }
        catch (MySql.Data.MySqlClient.MySqlException ex)
        {
            ModelState.AddModelError("", ex.ToString());
        }
        catch (Exception ex)
        {
            ModelState.AddModelError("", ex.ToString());
        }

        return View();
    }

    // other useful action methods...
}

For testing, i'm inserting an "Invoice" object that has a duplicate data (unique column) in the database expecting to throw an exception and then my action catching it and display properly the error in the view but... the exception is "thrown" but is not "catched".

I debugged to see what kind of exceptions are thrown (including their inner exceptions) and added the required "catches" but still the exception is not "catched".

If i change the code of the controller to use the "MySQLContext.cs" class directly to save the info the exception is "catched":

    [HttpPost]
    public async Task<ActionResult> Upload(Invoice invoice)
    {
        try
        {
            // this is "catched" ¿?
            this.db.Invoices.Add(obj);
            await this.db.SaveChangesAsync();
        }
        catch (Exception ex)
        {
            ModelState.AddModelError("", ex.ToString());
        }

        return View();
    }

Why is this happening? I need to be able catch any exception that my "Insert" or any other function in the "InvoiceRepository" class throw inside the controller.

Any help would be appreciated.

prueba prueba
  • 652
  • 1
  • 8
  • 26
  • this is a really bad way to deal with errors like that to be honest. You could simply do a few extra checks to make sure you're not trying to insert a duplicate value. If the value exists then return something and deal with it nicely instead of throwing errors everywhere.There is a cost associated with throwing exceptions – Andrei Dragotoniu Jul 28 '17 at 15:57
  • I can do that but i need to be prepared to catch any kind of exceptions. No matter how many validations i perform, my code has to be ready to catch any exception is thrown. – prueba prueba Jul 28 '17 at 16:04

1 Answers1

2

You are not awaiting the Insert method so it's not possible for your action to catch any exception. Visual Studio should have given you a warning message that nothing has be awaited in that method. Change your code to this:

await this.invoices.Insert(invoice);

Also, your repository should not use async void, it should return a Task

DavidG
  • 113,891
  • 12
  • 217
  • 223