views:

257

answers:

3

Hi,

i am kind of stuck with this code:

    [AcceptVerbs(HttpVerbs.Post), Authorize]
    public ActionResult Edit(FormCollection collection, [Bind(Exclude="Id,Latitude,Longitude")]Store bindStore, string Latitude, string Longitude)
    {
        Store st = storeModel.GetStore(Session["user_id"].ToString());
        bool modelUpdate = TryUpdateModel(st, new string[] { "Storename", "Address1", "Address2", "Zipcode", "City", "Phone1", "Phone2", "Store_email", "Store_homepage", "Pm_ec", "Pm_visa", "Pm_master", "Appointment_requirement", "Short_user_store_description" });

        if (ModelState.IsValid)
        {
            storeModel.Save();
            return RedirectToAction("ImageUpload");
        }
        else
            return Edit();
    }

My problem is, that i don't know whats the right way to do the ModelBinding, when i need these conditions to match:

  • The "Store" object has several fields ( not only Id ) that should NOT be updated during this update ( had problems that the "TryUpdateModel" NULL-ifies all these fields, so i added the "includeProperties" value with the cleartext of all the params.. a solution i don't like anyway)
  • Getting the store id from session as i don't want it to be in the HTML
  • Making InputValidation through the DataAnnotationModel ( see below )

     [MetadataType(typeof(StoreMetaData))]
     public partial class Store
     {
     }
    
    
     public class StoreMetaData
     {
       [Required]
       [StringLength(5)]
       public object Storename { get; set; }
     }
    

Question: Is this the right approach or is there a standard/nicer solution for this kind of problem?

A: 

My guess, from looking at the code you posted, is that you're trying to make it so that the Edit view will only allow certain fields to be edited, but 'pass through' the ones you don't want changed. In that case, you can modify your Edit view to remove those fields from being edited, but still send them over in the form using:

<%= Html.Hidden("field") %>

Let me know if this is what you intended.

Daniel T.
no, lets say there is more than 1 view and the both update 50% of the fields of the store object..
David
Are the views updating the same data? Can you elaborate your original post a bit more with the structure of your program?
Daniel T.
I guess you get me wrong.. it's not about the views ( they just contain "some" of the fields of the "store" object ).. the HTTP-Post request contain these fields and the ModelBinder sets all other fields in the "bindStore" parameter to null..
David
What are you sending to the views?
Daniel T.
+1  A: 

You don't need formcollection in parameters for start. And no, updatemodel will try to update all fields of model if no white or black list defined. So either that or create your own function to update your model objects.

Maybe somethig generic. that will reflection enumerate properties of supplied update object and apply those that are not null to object being updated.

Alexander Taran
A: 

Your way is fine IMHO.

There are other options but none of them provide a compelling benefit over your technique.

The only thing I would do differently is to model bind to custom ViewModel with the exact fields you need and then do the rightly-lefty code to assign just those values:

public ActionResult Edit( SlimStoreViewmodel editStoreModel, string Latitude, string Longitude)
{
    Store st = storeModel.GetStore(Session["user_id"].ToString());

    if (ModelState.IsValid)
    {            
        st.Thing = editStoreModel.Thing;
        st.Thing2 = editStoreModel.Thing2;
        st.Widget = editStoreMOdel.Widget;

        storeModel.Save();
        return RedirectToAction("ImageUpload");
    }
    else
        return Edit();
 }

This gets rid of long magic string dense things like this:

TryUpdateModel(st, new string[] { "Storename", "Address1", "Address2", "Zipcode", "City", "Phone1", "Phone2", "Store_email", "Store_homepage", "Pm_ec", "Pm_visa", "Pm_master", "Appointment_requirement", "Short_user_store_description" });
jfar
Yeah, but this way i have to manually define the ViewModel which i wouldn't like to, because i have a very lot of constructs like the above... and the maintainance would be a real pain
David