views:

512

answers:

1

I'm wondering if there is a good example of how to edit ASP.NET Profile settings in MVC using model binding.

Currently I have:

  • a custom ProfileCommon class derived from ProfileBase.
  • a strongly typed view (of type ProfileCommon)
  • get and post actions on the controller that work with ProfileCommon and the associated view. (see code below).

Viewing the profile details works - the form appears all the fields are correctly populated.

Saving the form however gives exception:System.Configuration.SettingsPropertyNotFoundException: The settings property 'FullName' was not found.

Thinking about this it makes sense because the model binding will be instantiating the ProfileCommon class itself instead of grabbing the one of the httpcontext. Also the save is probably redundant as I think the profile saves itself automatically when modified - an in the case, probably even if validation fails. Right?

Anyway, my current thought is that I probably need to create a separate Profile class for the model binding, but it seems a little redundant when I already have a very similar class.

Is there a good example for this around somewhere?

    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult Edit()
    {
        return View(HttpContext.Profile);
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(ProfileCommon p)
    {
        if (ModelState.IsValid)
        {
            p.Save();
            return RedirectToAction("Index", "Home");
        }
        else
        {
            return View(p);
        }
    }
+1  A: 

It sounds correct when you say that the ProfileCommon instance is created from scratch (not from the HttpContext) in the post scenario - that's what the DefaultModelBinder does: it creates a new instance of the type based on its default constructor.

I think you could solve this issue by creating a custom IModelBinder that goes something like this:

public class ProfileBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext,
        ModelBindingContext bindingContext)
    {
        return controllerContext.HttpContext.Profile;
    }
}

You may need to do some casting to make it fit your profile class.

To use this ProfileBinder, you could then add it to your Edit controller action like this:

public ActionResult Edit([ModelBinder(typeof(ProfileBinder))] ProfileCommon p)
Mark Seemann
Thanks Mark, I think that would probably work but I think I'm attempting to do this the wrong way. The problem is that if any validation checks on the ProfileCommon class fail, the changes are already applied, the object marked as dirty and written out anyway. I've solved this now by using a second similar class (ProfileEdit) that has the validation logic and methods to apply to/from the ProfileCommon class. It's more code but separates it nicely and it just works.
cantabilesoftware