0

I'm trying to design a N-Tier Solution for my existing WebAPI project.

I have a WebAPI project where, as of now, all the business logic are written in the controllers and the data validation are done by annotations.

This is now leading to duplicate code across controllers when I'm trying to implement same logic.

So I thought of moving my Business Logics to Business Layer. But I'm mostly facing challenges in returning Business Validations to controller.

For E.g I have a code portion in controller like

//Check if User is adding himself
            if (RequestUser.Email == model.Email)
            {
                return BadRequest("Email", "You cannot add yourself as an User");
            }

Now how do I return BadRequest from Business Class Methods?

And it's getting tough when the next line of the controller is

IdentityResult result = await UserManager.CreateAsync(user);

                if (!result.Succeeded)
                {
                    return result;
                }

So I cannot return both BadRequest & IdentityResult from same method. Also BadRequest, ModelState is not accessible in controllers. Ofcourse I can add System.Web.Mvc there in BLL, but would that be a good idea?

Another thing that I'd like to know is, I'm just creating Methods inside BLL's which are taking ViewModels that I receive in controllers. Is that a good idea for existing project? Or should I create DTO's (same as like Models) in BLL and use AutoMapper to map the properties and let BLL operate on DTO's instead of passing ViewModels.

I think the latter would be more extendable, but would require more time.

Lastly, if you do suggest me to go with DTO's, then I have to change at BLL DTO's as well as in Model when introducing new properties, isn't that a bad idea? Code is then duplicating here too. On other side, as of now, I change all the related ViewModels too (sometimes 2-4) (which I think is not the right approach) when adding a new property to Models.

So what's the right approach?

2 Answers 2

2

There are several ways you can approach this.

  • return some value that indicates an error condition, such as null.

  • throw an exception.

  • wrap your DTO in some sort of "maybe" object that returns both your DTO and some status information.

  • Use the Unit of Work pattern.

The right approach is the one that most effectively meets your specific requirements.

1
  • Thanks a lot, but other thread are suggesting, throwing exception is a costly affair and not to use the same. Also I want to use the ModelState & IdentityResult for showing error messages in UI. So any idea on how can I return these type of objects to Controller? In some cases, I need to return both or either of them and that's where I'm stuck. Jan 3, 2017 at 11:48
1

It would be inappropriate to throw BadRequest from the business layer since the BL shouldn't have any dependencies to the web interface layer and in principle shouldn't know it is executed as part of a web request. The easiest solution is just to throw an business logic exception which is defined at the BL layer, and then handle it at the controller layer.

The BL layer should not have any dependencies to the ViewModel's either, for the same reason. You should use models which are independent of any specific views in the BL layer. These models does not have to be DTO's though. They could be any kind of business object.

You could use automapping to copy data between view model and model. But you should perhaps consider if you need view models at all then? If the view model is just reflecting the model 1:1 you don't really need the additional layer of view models. I suggest only introducing view models when you actually need them.

3
  • Well now it's a bit more clear. But say my Model have 10 properties and VM have 3. And at a future point, I need another property in Model, so I have to 1. Add a property in Model, 2. Add a property in VM (considering it's needed there too) and 3. I need to change the configuration of Automapper and calling points. So considering the situation, isn't it a code duplication and breaking the principle of SOLID? For a single change, i need to change 3 areas of my application. Jan 3, 2017 at 11:18
  • @KrishnanduSarkar: Yes, this is why I say you should consider if you need a seperate VM at all. If the VM is just a direct copy of the model there is no benefit to having a distinct view model. View models make sense is there is some additional formatting or presentation logic rather than just direct copying of model data.
    – JacquesB
    Jan 3, 2017 at 12:32
  • Well my situation is like, say I have a model with 5 properties in it, and I have marked them with Required attribute as in DB those should be not nullable fields. But those same fields won't be sent by users via WebAPI, and those are something that I'll generate instead with some application / business logic. So as of now, I have created a VM (received by controller) which is identical to the model, but only except the fields that users do not need to send. I hope this is a right approach to do the same. Jan 4, 2017 at 6:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.