C# and .Net Best Practices Question

Brian Ashcraft 100 Reputation points
2023-02-17T02:14:02.2166667+00:00

Hello All,

Ran into a situation today, and I wanted to query those with more experience than me on how to best handle it.

I am writing an ASP .Net 6 webapp using c# and Razor Pages (not MVC).

My app uses hashtags.

I have an administrative backend where users with certain OAuth credentials can perform CRUD operations on many different types of data used in the app.

I have a directory /Hashtags as part of that administrative backend.

Inside that folder, I have an Index.cshtml and its associated CRUD .cshtml pages we well.

The Hashtag class looks like this (very simple):

public class Hashtag
{
    [Key]
    public int Id { get; set; }

    [Required]
    [StringLength(50, ErrorMessage = "Name cannot be longer than 50 characters.")]
    public string Name { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "Description cannot be longer than 100 characters.")]
    public string Description { get; set; }
}

The OnPost /Hashtags/Create.cshtml looks like this:

public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    //Ensure Hashtag starts with no more that one #
    Hashtag.Name = Hashtag.Name.TrimStart('#');

    //Prepend Hashtag with # if not already there
    if (!Hashtag.Name.StartsWith("#"))
    {
        Hashtag.Name = "#" + Hashtag.Name;
    }

    //Ensure Hashtag is unique
    if (_context.Hashtag.Any(c => c.Name == Hashtag.Name && c.Id != Hashtag.Id))
    {
        ModelState.AddModelError("Hashtag.Name", "Hashtag already exists");
        return Page();
    }

    _context.Hashtag.Add(Hashtag);
    await _context.SaveChangesAsync();

    TempData["Created"] = "Hashtag Successfully Created";
    return RedirectToPage("./Index");
}

While working on the app today I realized that I am not always going to want to create Hashtags from the /Hashtage/create.cshtml page. I will want to create them from several different pages throughout the app.

I considered creating an overloaded Constructor in the Hashtag.cs class file, but after doing some research the consensus seems to be that doing heavy work via a Constructor is frowned upon by some large percentage of the dev community.

I could be wrong on this, so please correct me if I am wrong.

I finally decided on creating a Method (using a .cs file) in the /Hashtags directory.

That Method looks like this:

 public class HashtagCreateMethodPageModel : PageModel
 {

     public async Task<int> AddHashtagAsync(string name, string description, ApplicationDbContext _context)
     {
         Hashtag objHashtag = new()
         {
             Name = name,
             Description = description
         };

         //Ensure Hashtag starts with no more that one #
         name = name.TrimStart('#');

         //Prepend Hashtag with # if not already there
         if (!name.StartsWith("#"))
         {
             name = "#" + name;
         }

         //Ensure Hashtag is unique
         if (_context.Hashtag.Any(c => c.Name == name))
         {
             int hashtagId = 0;
             return hashtagId;
         }
         else
         {
             //Update objHashtag
             objHashtag.Name = name;

             //Insert new Hashtag using Name and Description
             _context.Hashtag.Add(objHashtag);
             await _context.SaveChangesAsync();

             //Get the Hashtag.Id to the Id of the newle Created Hashtag
             int hashtagId = objHashtag.Id;

             return hashtagId;
         }
     }
 }

This method accepts the two Hashtag parameters and returns a Hashtag.Id.

But now it occurs to me that I have two separate places in my code that service the Creation of a Hashtag, and this seems to be a problem.

My question is this...

How can I make this code more efficient, and perhaps single up my Create code to a single instance of the operation?

Appreciate any advice offered.

Thanks!

Entity Framework Core
Entity Framework Core
A lightweight, extensible, open-source, and cross-platform version of the Entity Framework data access technology.
779 questions
.NET
.NET
Microsoft Technologies based on the .NET software framework.
4,103 questions
ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,803 questions
ASP.NET
ASP.NET
A set of technologies in the .NET Framework for building web applications and XML web services.
3,598 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
11,338 questions
{count} votes

Accepted answer
  1. AgaveJoe 29,946 Reputation points
    2023-02-17T12:32:44.7233333+00:00

    Best practice is a layered application where the DbContext and entities are in a separate library or namespace or class or web service. This is essentially the recommendation from Karen and Zhi Lv - MSFT.

    General search terms are "3-tier architecture" or "layered application design". In ASP.NET Core these layered concepts are brought to life using ASP.NET Core's dependency injection.

    Dependency injection in ASP.NET Core

    1 person found this answer helpful.
    0 comments No comments

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.