1

In my view this is what I have

        @foreach (var match in Model.CommonMatches)
        {
            <tr>

                <td>@match.StartDateTime</td>
                <td>@match.EndDateTime</td>
                <td>@match.AvailableAttendees.Count()</td>
                <td>@Html.ActionLink("Accept", "AcceptAppointment", "Appointment", new {commonMatch = @match })</td>
            </tr>
        }

Model.CommonMatches is of type List<Window>

public class Window
{
    public DateTime StartDateTime { get; set; }
    public DateTime EndDateTime { get; set; }
    public IEnumerable<DataModels.Attendee> AvailableAttendees { get; set; }

}

This is how the value is being passed from controller

[HttpGet]
public ActionResult ViewStatus(Guid appointmentId)
{
    var status = new ViewStatus
    {
        AttendeesWhoResponded = _appointmentRepository.GetAppointmentDetails(appointmentId).Attendees.Where(a=>a.HasResponded == true).ToList(),
        NotAttending = _appointmentRepository.GetAppointmentDetails(appointmentId).Attendees.Where(a=>a.HasResponded == true && a.Responses == null).ToList(),
        CommonMatches = _appointmentRepository.FindCommonMatches(appointmentId)
    };
    return View(status);
}

ViewStatus class

public class ViewStatus
{
    public ViewStatus()
    {
        AttendeesWhoResponded = new List<DataModels.Attendee>();
        NotAttending = new List<DataModels.Attendee>();
    }
    public List<DataModels.Attendee> AttendeesWhoResponded { get; set; }

    public List<DataModels.Attendee> NotAttending { get; set; }
    public IEnumerable<Window> CommonMatches { get; set; }
}

The action in controller that ActionLink of view is calling is:

[HttpGet]
public ActionResult AcceptAppointment(Window commonMatch)
{
    return Content("ac");
}

When I inspect the value of commonMatch in controller's action. I'm getting the StartDateTime and EndDateTime but i'm not getting all the value of AvailableAttendees. It is currently shown as null.

AvailableAttendees that I'm expecting is of type IEnumerable<Attendee>. Is is not possible to pass the object the way I'm passing?

What should I do, to also get all the values of AvailableAttendees in controller along with dates?

Edit 1:

<table class ="table-hover table-striped">
    <thead>
        <tr>
            <td>Start time</td>
            <td>End time</td>
            <td>Number of Attendees</td>
        </tr>
    </thead>


            @for (var count = 0; count < Model.CommonMatches.Count();count++ )
            {
                using (Html.BeginForm("AcceptAppointment", "Appointment", FormMethod.Post))
                {
                    <tr>
                        <td>@Model.CommonMatches[count].StartDateTime</td>
                        <td>@Model.CommonMatches[count].EndDateTime</td>
                        <td>@Model.CommonMatches[count].AvailableAttendees.Count()</td>
                        @*<td>@Html.ActionLink("Accept", "AcceptAppointment", "Appointment", new { commonMatch = @match })</td>*@


                    @for(var j=0;j<Model.CommonMatches[count].AvailableAttendees.Count();j++)
                    {
                        <td>@Model.CommonMatches[count].AvailableAttendees[j].FirstName</td>//to check if the value is null or not, just a test
                        <td>@Html.HiddenFor(m=>Model.CommonMatches[count].AvailableAttendees[j].FirstName)</td>
                        <td>@Html.HiddenFor(m=>Model.CommonMatches[count].AvailableAttendees[j].LastName)</td>
                        <td>@Html.HiddenFor(m=>Model.CommonMatches[count].AvailableAttendees[j].Email)</td>
                        <td>@Html.HiddenFor(m=>Model.CommonMatches[count].AvailableAttendees[j].AttendeeId)</td>
                    }
                        <td><input type="submit" value="Accept"/></td>
                     </tr>

                }
            }


</table>
Cybercop
  • 8,475
  • 21
  • 75
  • 135

2 Answers2

2

You need to post your model back, this would involve changing your controller method to this:

Controller

[HttpPost]
public ActionResult AcceptAppointment(List<Window> model)
{
    return Content("ac");
}

View

You view would need a form and a submit button rather than an ActionLink. I have take the table formatting out to simplify the below.

Indexing your collections with a for loop so the model binder knows how to handle them, this is actually two loops as it is a collection within a collection. The hidden values have to be rendered too in order to be posted back (please forgive any typos).

@for(var i = 0; i < Model.CommonMatches.Count; i ++)
{
            <div>
                @using (Html.BeginForm("AcceptAppointment", "Appointment", FormMethod.Post)
                {
                @Html.HiddenFor(m => Model.CommonMatches[i].StartDateTime)
                @Html.HiddenFor(m => Model.CommonMatches[i].EndDateTime)
                @Model.CommonMatches[i].StartDateTime <br/>
                @Model.CommonMatches[i].EndDateTime <br/>

                @for(var j = 0; Model.CommonMatches[i].AvailableAttendees.Count; j++)
                {
                      @Html.HiddenFor(m => Model.CommonMatches[i].AvailableAttendees[j].Prop1)<br/>
                      @Html.HiddenFor(m => Model.CommonMatches[i].AvailableAttendees[j].Prop2)<br/>
                }

                 <input type="submit" value="Accept" />
        </div>
        }
}
hutchonoid
  • 32,982
  • 15
  • 99
  • 104
  • I think this would work, but i need to find how to have a `` tag inside table. Now its saying it is not possible to have tag inside table. Do you have any idea? – Cybercop Feb 25 '14 at 12:58
  • @Biplov13, `` cannot be a direct children of ``. But it can be under `
    `
    – Murali Murugesan Feb 25 '14 at 13:02
  • @Murali so I need to create a tag for tag, how about hidden values, do they also need to be inside ? because the i'm not getting any data right now. – Cybercop Feb 25 '14 at 13:05
  • @Biplov13 Yes, they can all be inside 's. – hutchonoid Feb 25 '14 at 13:09
  • for some strange reason, In controller it says `AvailableAttendees Count = 0` I tried checking if the property contains values or not, and found out that it does contain the value. – Cybercop Feb 25 '14 at 13:16
  • @Biplov13 Seems odd, someone may correct me but I think it might be because it is an IEnumerable, try changing it to a list. You could always add a property to the Match model, public string AvailableAttendeeCount { get; set; }, set it in your get and render it as another hidden field. – hutchonoid Feb 25 '14 at 13:22
  • @hutchonoid I have changed it to List – Cybercop Feb 25 '14 at 13:24
  • or If I could pass the value of `i` to controller, i could load the list that that i have passed to view and find all the information. But would that be possible? – Cybercop Feb 25 '14 at 13:27
  • @Biplov13 think i is usually the count of the object in the collection when posted back. – hutchonoid Feb 25 '14 at 13:38
  • I just realized it doesn't even pass the value for StartDateTime and EndDateTime, because the Id generated for these dates also include the index and while posting, may be it doesn't bind these values. Probably i need some editor templates – Cybercop Feb 25 '14 at 14:00
  • @Biplov13 Hi, sorry. The view model will be posted back as a List model. I've changed the controller method in the answer. That will post it all back for you. – hutchonoid Feb 25 '14 at 14:17
  • I tried with List in controller but now it says commonMatch value is null – Cybercop Feb 25 '14 at 15:11
  • I think the issue is if you want to post a single the form is in the correct place but the controller parameter should be Window commonMatch but if you want a list to be posted the parameter should be List and the form moved to include all the loops in the list if that makes sense. You might be right about creating an editor template for them, it could simplify it a lot. – hutchonoid Feb 25 '14 at 15:28
2

There are plenty of things you need to taken care

<td>@Html.ActionLink("Accept", "AcceptAppointment", "Appointment", new {commonMatch = @match })</td>

Calls

[HttpGet]
public ActionResult AcceptAppointment(Window commonMatch)
{
    return Content("ac");
}

Here you are navigating using a link <a href>. Basically you are issuing a get request. In get request, you can pass the data to server only via Query String. But your case, preparing a query string dynamically before navigating to url is bit more complex. But you can do it with a JavaScript like onclick=prepareHref(this);

@Html.ActionLink("Accept", "AcceptAppointment", "Appointment", 
  new {commonMatch = @match }, new {onclick=prepareHref(this)})

Then in Javascript

function prepareHref(obj)
{
 var qsData="?StartDateTime='2014-02-25'&EndDateTime='2014-02-25'&AvailableAttendees[0].prop1=value1, etc"; // data should be obtained from other td elements
 obj.href=obj.href+qsData;
}

But this is not a suggested way of doing it.

In case, if you want to open other page and show the url, better pass the id and load data again.

Option 1:

The better way could be submit the detail in the hidden field as explained by @hutchonoid.

Option 2:

or submit the details in jQuery ajax $.post method. Either way you need to use POST

@Html.ActionLink("Accept", "AcceptAppointment", "Appointment", 
  new {commonMatch = @match }, new {onclick=postMyData()})


function postMyData(){
    var postData={};
    postData.StartDateTime='';
    postData.EndDateTime='';
    postData.AvailableAttendees=[];
    //for each AvailableAttendees prepare object
    postData.AvailableAttendees[0]= {};
    postData.AvailableAttendees[0].prop1=value1;



    $.post('/Appointment/AcceptAppointment/',{data:postData},function(data){

    });
    return false;
}

[HttpPost]
public ActionResult AcceptAppointment(Window commonMatch)
{
    return Content("ac");
}
Murali Murugesan
  • 22,423
  • 17
  • 73
  • 120