0

I have been working through the official Microsoft tutorial intended to teach the use of C# ASP.NET Core MVC (https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/crud). I have experience with OOP languages like C++ and Java, but I'm new to both C# and this specific framework.

The tutorial itself is working great; I have a web app that can perform basic CRUD operations on students. For my purposes, all that's important to know is that a student has a LastName, FirstName and a unique, automatically generated ID which functions as its primary key in the database.

I'd like to add a check to ensure that the combination of the student's last and first name is unique. I would also like to be able to sanitize the input by removing leading spaces, etc. I was able to do this with the creation of new data in the Create method, but I'm lost as to how to add this to the recommended Edit method in the controller (I've trimmed everything I know isn't vital from the below to save space):

[HttpPost, ActionName("Edit")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> EditPost(int? id) 
{
    var studentToUpdate = await _context.Students.SingleOrDefaultAsync(s => s.ID == id);

    if (await TryUpdateModelAsync<Student>(
        studentToUpdate,
        "",
        s => s.FirstMidName, s => s.LastName))
    {
        try
        {
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
    }

    return View(studentToUpdate);
}

QUESTION: how can I check and manipulate the user's data before it is put in the database?

From what I've been able to dig up, TryUpdateModelAsync function is somehow getting the information the user submits and using it to update the model. However, the documentation hasn't given me any clue how I could intervene and become an active part of that process. I'd like to check/manipulate the data myself before allowing the update, but I'm not sure how to access it. Is it in an object? Is there a function that can let me run operations on it? After a full day of Googling, I have yet to find it. I'm sure it must be possible, because putting unsanitized data fresh from the user into a database doesn't seem like a good practice. (at least that's what I heard from Bobby Tables)

An example of input in the view, in case it helps:

<div class="form-group">
    <label asp-for="FirstName" class="control-label"></label>
    <input asp-for="FirstName" class="form-control" />
    <span asp-validation-for="FirstName" class="text-danger"></span>
</div>

I hope I've provided enough information; if there's any important context I'm leaving out, please let me know.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • 1
    First your editng data so you should be using a view model (refer [What is ViewModel in MVC?](https://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc)). Second, the parameter in you method should be that view model. Then you can manipulate the values when your mapping the view model to the data model before saving the data model. –  Aug 31 '17 at 00:16

2 Answers2

0

The student data is in "studentToUpdate". You can read and write to it like this.

studentToUpdate.firstName = "anything"
var fullName = studentToUpdate.firstName + " " + studentToUpdate.lastName
if (studentToUpdate.lastName == "anything")
{
    //Do anything here
}

Please note that it seems like you are reading the database and saving the data again without posting anything from your form. Your controller has a mix of HTTP GET and HTTP POST. Please have a look on this tutorial:

https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/crud

Also for validation of the input data, I suggest you use on your model validation attributes. Please have a look on this tutorial:

https://learn.microsoft.com/en-us/aspnet/core/mvc/models/validation

  • I'm not sure what you mean when you say the controller has a mix of GET and POST. The code I posted matches the code from the "Recommended HttpPost Edit Code" section on the page you linked to. When I run it, it works: the database is updated (data is changed and data persists through multiple runs). – Always a Newb at Something Aug 31 '17 at 15:10
  • I did some tests and verified that studentToUpdate contains data from the currently existing model, not the user's input. Changes to this data will change the current model, but are not entered into the database. When the Edit Page is closed, changes made to this data will be lost. If the TryUpdateModelAsync method is called after making this change, it will be as if this change was never made. – Always a Newb at Something Aug 31 '17 at 15:13
  • Thank you for suggesting the validation! I was able to write a function for the CustomValidation attribute to take care of detecting and failing in situations with "bad" white space. Haven't figured out how to incorporate multiple form inputs into a single check, though, since Validation seems to work on only one input at a time. – Always a Newb at Something Aug 31 '17 at 23:33
0

About the validation part, you should use Model validation attributes. In your specific example, you have to check DB if your student already exists :

In your ViewModel :

@using System.Web.Mvc

//your model properties

[Remote("CheckStudentNameAlreadyExists", "Validation", ErrorMessage = "This student already exists")]
public string StudentName {get; set;}

Then, just write a method in your ValidationController which checks if a student already exists, following your own business rules

public JsonResult CheckStudentNameAlreadyExists(string studentName)
{
    bool isNameAvailable = /* method checking your DB */
    return Json(isNameAvailable , JsonRequestBehavior.AllowGet);
}

About the modification part, your EditPost action should have your viewModel as parameter, so you may then modify data "on-the-fly".

AlexB
  • 7,302
  • 12
  • 56
  • 74
  • Regarding modification, the tutorial's recommended EditPost action's only parameter is an ID. However, the Create method declaration is as follows: `public async Task Create( [Bind("FirstMidName,LastName")] Student student)`. Is the parameter Create takes the viewModel you are referring to? Something similar to that was initially a second parameter for the EditPost action, but the tutorial recommended we remove it. – Always a Newb at Something Aug 31 '17 at 15:25