ASP.NET MVC – Options for Exposing Customization Settings to the Admin User

asp.net-mvc

I'm writing a blog system as a learning exercise and I would like to allow the admin (or blog owner) to select/change some custom options based on features that I choose to expose to them such as:

  • change blog name (string)
  • select layout (int)
  • number of blog entries per page (int)
  • more stuff like this…

The only way that I can really think of to do this is by creating a class, with a property for each option and letting the owner get and set the properties.

What are my options for exposing customization settings to the admin / owner?


This is how I've implemented it for the time-being, although I am aware that this may not be the best way to do this:

I've created a class called Setting.cs

    public class Setting : IEntity
    {
        [Key]
        public int Id { get; set; }
        public string BlogName { get; set; }
        public string SubTitle { get; set; }
        public int PostsPerPage { get; set; }

    }

Then I added a settings method to my Admin Dashboard controller like this:

    public ActionResult Settings(int? id = 1)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Setting set = db.Settings.Find(id);

        if (set == null)
        {
            return HttpNotFound();
        }
        return View(set);
    }


    [HttpPost]
    [ValidateAntiForgeryToken]
    [ValidateInput(false)]
    public ActionResult Settings([Bind(Include = "Id,BlogName,SubTitle,PostsPerPage")] Setting sets)
    {
        if (ModelState.IsValid)
        {
            db.Entry(sets).State = System.Data.Entity.EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index", "Dashboard");
        }
        return View(sets);
    }

I then seed the record and just retrieve the same record and update it with the new settings each time.

I suppose I should state my concerns:

  • It seems strange to store a single row of data in it's own table of my database.
  • It also seems strange that if one wanted to, one could instantiate the Settings.cs class and possibly make multiple records of it.
  • I've hard-coded my controller with the record ID, as well as any calls to the controller, which to me feels like I'm abusing the intended purpose of using a controller by hard coding it.

I'm new to programming but this doesn't seem right to me. In Swift iOS programming I could create a pList (flat-file) or store settings in the NSUserDefaults. I'm just wondering what my options are in ASP.NET MVC.

I originally wanted to ask "What's the best way to implement admin/owner settings?" but I didn't want my question closed as being subjective. I am, however, hoping to deduce what the preferred method is ultimately to adhere to best practices.

Best Answer

My experience is that the "settings" supported by C# out of the box are not very useful.

Storing the settings in the database is a much better idea for a number of reasons.

  1. It will be possible to take a complete backup of the blog by backing up the database without having to remember what other files you need.

  2. If you one day decide to take this system of yours, which currently implements a single blog for a single user, and turn it into a blogging platform supporting many blogs operated by multiple users, you will just create multiple settings records, one for each user, and at least that part will be taken care of. With a settings file, such a thing would be impossible, you would certainly have to rewrite your settings mechanism to make use of the database at that point.

  3. Your settings may need to refer to rows in the database, in which case it only makes sense to also store the settings in the database in order to enjoy the benefits of referential integrity checking. For example, you may wish to add a setting for a "sticky post" which is to always be displayed first, regardless of how old it is. If you go with a settings file, then the "sticky post id" setting will be just a meaningless number, interpreted by your code to (hopefully) correspond to a blog post. If you store your settings in the database, then the RDBMS will ensure that this number will in fact be the actual id of an existing row in the blog posts table. (Or NULL, if you don't want a sticky post.)

Need I go on?

The way this is usually accomplished is by having a settings table with a single row in it. This is not just a wild idea that you had, it is a legitimate technique which has actual application in the real world.

There is no way to guarantee that additional rows will never be accidentally added to the settings table, but at least you can count the rows during startup and display an error message if more than one row is found.

You can easily guarantee that there will always be only one instance of the settings object by adding a private static bool member to it, and Asserting from the constructor of the object that this bool is false, then setting it to true. This means that the constructor may only be invoked once.