Michael Conklin
Michael Conklin

Reputation: 101

MVC Separation of Concerns

so I was going on creating my MVC 3 web app when it dawned on me that I might be putting entirely too much logic in my Controller, that it needs to be in the Model instead. The problem with this is, that in this particular instance I'm dealing with a file.

The SQL database table stores the path of the file, and the file itself is saved in a directory. So in the database, the file path is stored as an nvarchar, and in the model, the file is a string, everything's consistent to that point. The issue comes when it's time to upload the file, at that point I'm dealing with a System.IO.File.

So the question is, how do you provide System.IO.File logic inside the model for the file when in the back-end it is actually a string?

I had finished the functional version of the Controller and had some logic already in it, and was about to add more when I realized that I was working against the system. What I mean is that in order to have server-side validation, the logic needs to be in the Model in order for the input validation to behave and work according to proper MVC rules, obviously optionally using client-side validation in conjunction.

Currently...

Here is my View:

@model ProDevPortMVC3.Profile

@{
    ViewBag.Title = "Profile Photo Upload";
}

<h2>Photo Upload</h2>

<img alt="Profile Image" src="@Html.DisplayFor(model => model.ProfilePhotoPath)" />

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm("UploadPhoto", "Profile", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.ValidationSummary(true)
    <br />
    <input  type="file" name="File1" />
    @Html.ValidationMessageFor(model => model.ProfilePhotoPath)
    <input type="submit" value="Upload" />
}

Here is my Controller (just the relevant action method):

    [HttpPost]
    public ActionResult UploadPhoto(int id, FormCollection form)
    {
        Profile profile = db.Profiles.Find(id);

        var file = Request.Files[0];

        if (file != null && file.ContentLength > 0)
        {
            try
            {
                string newFile = Path.GetFileName(file.FileName);
                file.SaveAs(Server.MapPath("/Content/users/" + User.Identity.Name + "/" + newFile));
                profile.ProfilePhotoPath = "/Content/users/" + User.Identity.Name + "/" + newFile;
                UpdateModel(profile);
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }
        return View();
    }

And here is my Model (just the part relevant to the file):

    public string ProfilePhotoPath { get; set; }

So I guess, what are your guys' solutions in these particular situations?

Upvotes: 4

Views: 453

Answers (2)

dknaack
dknaack

Reputation: 60438

Description

Assuming i understand your question. I have read your question a few times. ;) If i don't understand, please comment my answer in order to get a better answer (i will update)

I think that you want is.. How to Model Validation for your particular case.

You can add Model Validation errors using the ModelState.AddModelError("Key", "Message) method.

ModelState.AddModelError Adds a model error to the errors collection for the model-state dictionary.

Sample

ModelState.AddModelError("ProfilePhotoName", "YourMessage");

This will affect ModelState.IsValid

So you can do whatever you want (your logic) and can make your Model invalid.

More Information

Upvotes: 1

Jimmy Miller
Jimmy Miller

Reputation: 1319

There are any number of answers to this question. I'll take a crack at it knowing the risk going in due to varying opinion. In my personal experience with MVC3 I like to use flatter, simpler Models. If there is validation that can be done easily in a few lines of code that doesn't require external dependencies then I'll do those in the Model. I don't feel like your System.IO logic is validation, per se. Validation that could go in the Model, in my mind, is whether the filename is zero length or not. The logic to save is something you can put in your controller. Better yet, you could inject that logic using the Inversion of Controller pattern and specifically a Dependency Injection solution.

Upvotes: 0

Related Questions