views:

228

answers:

2

Hi, I'm very new to this, so any help is appreciated.

I'll use the Dinners/RSVPs relationship for detailing my problem. One Dinner has many RSVPs. On my Dinner edit page/view I want to be able to edit the Dinner information AND the RSVPs information.

I have that part working, based on the answer given here by James S:

int i = 0;

foreach (var r in Dinner.RSVPs) {
  UpdateModel(r, "Dinner.RSVPs[" + i++ + "]");
}

But what if I want to Delete an RSVP based on the user clicking a checkbox next to the RSVP on the edit view? Something like this on the edit view:

<% int i = 0;  
    foreach (var rsvp in Model.RSVPs){%>
    <%=Html.CheckBox("RemoveRSVP[" + i + "]") %>
    <%= Html.TextBox("Dinner.RSVPs[" + i + "].Name", rsvp.Name) %>
<% i++;
}%>

I tried this, but it's not working, obviously:

Dinner dinner = dinnerRepository.GetDinner(id);
int i = 0;

    foreach (var r in dinner.RSVPs) {
      if (Boolean.Equals(RemoveRSVP[i], true){
          dinner.RSVPs.Remove(r);
      else
           UpdateModel(r, "Dinner.RSVPs[" + i+ + "]");
      i++;
    }

I can't delete/remove an RSVP using UpdateModel can I?

Let me know if anything isn't clear.

Thanks.

A: 

I am not totally familiar with the NerdDinner code but don't they use Linq to SQL for their backend? If that is the case I would think you could tackle this in a traditional web approach and append the record ID to the value of each check box in a list of items to be deleted. Then you could catch the collection of IDs on the server side and do a DeleteAllOnSubmit by passing a selection query of entities to the delete call? Let me know if you need more detail.

Andrew Siemer
A: 

I tried this, but it's not working, obviously:

Is your difficulty in actually making the delete go through? Or is it in processing the form to detect which ones should be deleted? e.g. which line doesn't work:

dinner.RSVPs.Remove(r);

or

if (Boolean.Equals(RemoveRSVP[i], true)

?

For #1

If your repository is backed by Linq 2 Sql and RSVP is an entity, you will usually have to cause DeleteOnSubmit() to be called in order for the record to be deleted from the database--just calling Remove() on the association will not be enough. You probably will add one of the following to your DinnerRepository to do this:

DinnerRepository.DeleteRsvp(RSVP item)
DinnerRepository.DeleteRsvp(Dinner dinner, RSVP rsvp)

Alternately, if you want LINQ to perform the delete automatically, you can edit the DBML as XML (right click, open with, XML Editor) and add the following attribute to the entity association:

<Association Name="..." ... DeleteOnNull="true" />

For #2

I usually construct this type of "repeating entity-delete checkbox" form so that the posted values are a list of the entity IDs I want to delete. To facilitate this I use an alternate CheckBox helper:

public static class HtmlExtensions
{
    /// <summary>
    /// Alternate CheckBox helper allowing direct specification of "name", "value" and "checked" attributes.
    /// </summary>
    public static string CheckBox(this HtmlHelper html, string name, string value, bool isChecked)
    {
        string tag = String.Format("<input type=\"checkbox\" name=\"{0}\" value=\"{1}\" {2}/>",
            html.AttributeEncode(name),
            html.AttributeEncode(value),
            isChecked ? "checked=\"checked\" " : ""
            );
        return tag;
    }
}

and create the checkboxes like so:

<%= Html.CheckBox("RemoveRsvpIds", rsvp.RsvpId.ToString(), false) %>

and consume the list like so:

public ActionResult TheFormInQuestion(int dinnerId, int[] removeRsvpIds)
{
    var dinner = DinnerRepository.GetDinner(dinnerId);

    foreach (var rsvp in dinner.RSVPs)
    {
        if (removeRsvpIds.Contains(rsvp.RsvpId))
        {
            // Perform Delete
        }
        else
        {
            // Perform Update
        }
    }

    // The rest
}

I can't delete/remove an RSVP using UpdateModel can I?

The purpose of UpdateModel() is to automagically copy property values from the posted form onto an already-existing object--not to create new or destroy existing entities. So no, not really. It wouldn't be the expected behavior.

daveidmx
I'm actually having issues with both. The first part now I've fixed. What good is Remove() if it doesn't actually remove anything?
johnnycakes
I think the idea is that an Entity has its own independent lifetime, so simply altering another entity's properties shouldn't cause the first one to become deleted. However you can indicate that you _want_ this to happen. I've edited my response to include how to do this.
daveidmx
@johhnycakes any progress? have you had an opportunity to try either solution?
daveidmx
Quick tests show all your methods to work! Thanks!
johnnycakes