1

Been searching around but couldn't find a direct solution to what I'm trying to achieve.

I've tried to include as much as needed but it's a very large project so hopefully you'll get the gist.

Overview: I have a view model that has several lists of objects within it. I am using two partial views for control over each of the list of objects, one for gathering the list of objects (which is held in a session), and the other for adding a list of said object into the list.

Update: As per comment - what I am looking to do is as follows - in the Index, fill out the existingIp model info, which is displayed through the addToListPartialView, then it will post to the ListPartialView to update the list through the session, handled backend in the controller, which will in turn display on the Index - the question ultimately is, how do I achieve this?

Problem: The issue I'm having is once I've added an object, through a partial view, to the object list, another partial view, how do I then pass this back to the main view?

Code:

Controller

public ActionResult AddExistingIp([Bind(Include = "Subnet, Cidr, Mask")]ExistingIp existingIp)
        {
            if(Session["pa_ipv4Session"] != null)
            {
                pa_ipv4 pa_ipv4 = (pa_ipv4)Session["pa_ipv4Session"];
                if(pa_ipv4.ExistingIps == null)
                {
                    pa_ipv4.ExistingIps = new List<ExistingIp>();
                }
                pa_ipv4.ExistingIps.Add(existingIp);
                ViewBag.pa_ipv4 = pa_ipv4.ExistingIps;

                return View("ExistingIpView", ViewBag.pa_ipv4);
            }
            else
            {
                pa_ipv4 pa_ipv4 = new pa_ipv4();
                Session["pa_ipv4Session"] = pa_ipv4;
                pa_ipv4.ExistingIps = new List<ExistingIp>();
                pa_ipv4.ExistingIps.Add(existingIp);
                ViewBag.pa_ipv4 = pa_ipv4.ExistingIps;

                return View("ExistingIpView", ViewBag.pa_ipv4);
            }

Index:

@model ViewModel
<div id="ExistingIpList">
                    @{Html.RenderPartial("ExistingIpView");}
                </div>
                <div id="addExisting">
                    @{Html.RenderPartial("AddExistingIp");}
                </div>

List Partial

@model IEnumerable<ExistingIp>

@if (Model != null)
{
    foreach (var ei in Model)
    {
        <div class="ui-grid-c ui-responsive">
            <div class="ui-block-a">
                <span>@ei.Subnet</span>
            </div>
            <div class="ui-block-b">
                <span>@ei.Cidr</span>
            </div>
            <div class="ui-block-c">
                <span>@ei.Mask</span>
            </div>
            <div class="ui-block-d">
                @ei.Id
                <a href="#" class="deleteExistingIp" cssclass="ui-btn ui-corner-all ui-shadow">Delete</a>
            </div>
        </div>
    }
}

Add to list partial:

@using (Html.BeginForm("AddExistingIp", "PA_IPV4"))
{
    <div class="ui-grid-c ui-responsive">
        <div class="ui-block-a">
            <span>
                @Html.EditorFor(m => m.Subnet)
                @Html.ValidationMessageFor(m => m.Subnet)
            </span>
        </div>
        <div class="ui-block-b">
            <span>
                @Html.EditorFor(m => m.Cidr)
                @Html.ValidationMessageFor(m => m.Cidr)
            </span>
        </div>
        <div class="ui-block-c">
            <span>
                @Html.EditorFor(m => m.Mask)
                @Html.ValidationMessageFor(m => m.Mask)
            </span>
        </div>
        <div class="ui-block-d">
            <span>
                @Html.EditorFor(m => m.Id)
                @Html.ValidationMessageFor(m => m.Id)
            </span>
        </div>
    </div>
    <div data-role="main" class="ui-content">
        <div data-role="controlgroup" data-type="horizontal">
            <input type="submit" id="addExistingIp" cssclass="ui-btn ui-corner-all ui-shadow" value="Add" />
        </div>
    </div>
}

ViewModel:

public Contact ContactDetails { get; set; }
[Required]
public bool ExistingAddress { get; set; }
public List<ExistingIp> ExistingIps { get; set; }
[Required]
[DataType(DataType.MultilineText)]
public string ExistingNotes { get; set; }
adricadar
  • 9,971
  • 5
  • 33
  • 46
JammAndTea
  • 195
  • 1
  • 8
  • 1
    Not entirely sure what your asking, but if one partial contains a form to add a new item, then when you post, you need to redirect back to the GET method so the view is reconstructed. But it would be far better performance to use ajax to post the form, and then just update the DOM with the new item –  May 07 '15 at 12:39
  • Sorry, I'll update the question and try and make it clearer - essentially what I want to be able to do is in the Index, fill out the existingIp model info which is displayed through the addPartialView, then it will post to the ListPartialView to update the list through the session which will in turn display on the Index. – JammAndTea May 07 '15 at 12:44
  • 1
    Which means when you post to the `AddExistingIp` and have saved the item, you need to redirect to the `Index() method`, not return the view. But using ajax would be far better performance and you can get rid of that awful use of Session –  May 07 '15 at 12:48
  • You mean remove the session completely? I've no database until submit and it allows models (lots of) to be traversed across pages and back, reading and writing. Is it that bad or is it a personal dislike? – JammAndTea May 07 '15 at 13:00
  • @JammAndTea He mean something I did in my answer. You have to `RedirectToAction("Index")` and there to take the list from the `Session` and to give it to the `Index` View. – adricadar May 07 '15 at 13:02
  • Bad and personal dislike :). [Some reasons here](http://stackoverflow.com/questions/5220980/is-it-a-good-practice-to-avoid-using-session-state-in-asp-net-mvc-if-yes-why-a). If your thinking that somehow avoiding calling the database when you create a new item is somehow going to increase performance, then you need to rethink what your doing and instead use a 'popup' form and post using ajax, and then update your list using the values from the form. This will be multiple times better performance than your current implementation. –  May 07 '15 at 13:08
  • @StephenMuecke aha ok cool - thanks for that, this data isn't sensitive and because of input could be scraped at any point so don't want interaction with db until certainty, and not for performance - reset assured I shall not be using session state for large amounts/important data. I do like the idea of a pop-up form with AJAX, shall look into it. – JammAndTea May 07 '15 at 13:14

1 Answers1

1

You can modify the AddExistingIp to just store the data. And to make a RedirectToAction Index. There you will take the data from Session and pass it to the Model.

[HttpPost]
public ActionResult AddExistingIp([Bind(Include = "Subnet, Cidr, Mask")]ExistingIp existingIp)
{
    if(Session["pa_ipv4Session"] != null)
    {
        pa_ipv4 pa_ipv4 = (pa_ipv4)Session["pa_ipv4Session"];
        if(pa_ipv4.ExistingIps == null)
        {
            pa_ipv4.ExistingIps = new List<ExistingIp>();
        }
        pa_ipv4.ExistingIps.Add(existingIp);
    }
    else
    {
        pa_ipv4 pa_ipv4 = new pa_ipv4();
        Session["pa_ipv4Session"] = pa_ipv4;
        pa_ipv4.ExistingIps = new List<ExistingIp>();
        pa_ipv4.ExistingIps.Add(existingIp);
    }

    return RedirectToAction("Index");
}

The Index Action will look similar with this, where you take data from Session and use it in your Model

public ActionResult Index()
{
    var viewModel = new ViewModel();

    // take data from Session
    pa_ipv4 pa_ipv4 = Session["pa_ipv4Session"] as (pa_ipv4);
    // some verification    
    // add the list from Session to model
    viewModel.ExistingIps = pa_ipv4.ExistingIps;

    return View(viewModel);
}

Also, I think your Index View you should at ExistingIpView you should pass the Model to display.

@model ViewModel
<div id="ExistingIpList">
    @{Html.RenderPartial("ExistingIpView", Model.ExistingIps);}
</div>
<div id="addExisting">
    @{Html.RenderPartial("AddExistingIp");}
</div>
adricadar
  • 9,971
  • 5
  • 33
  • 46
  • Your edit should solve that, need to create new instances of everything on page load, cheers. – JammAndTea May 07 '15 at 12:57
  • @JammAndTea I don't think I undestand what you mean, can you give me more details? – adricadar May 07 '15 at 13:00
  • I don't think think the above is correct, null reference in renderpartial existingIpView, model.existingIps as it hasn't been created at start up, you can't iterate through a list that doesn't exist. Should this/can this not be done through the controller? – JammAndTea May 07 '15 at 13:34
  • @JammAndTea Yes, this need to be done in `Index` Action as I mention "Index that will take the data from Session". – adricadar May 07 '15 at 13:42
  • I didn't notice that, sorry notifications aren't working for me, I did try it though but I get an error on the other partial which requires passing a model item of type existingIp (the object that is in the list). I'm doing this through @{Html.RenderPartial("AddExistingIp", new Project.Models.ExistingIp());} - is this the only/best way? – JammAndTea May 07 '15 at 13:57
  • @JammAndTea I don't know if is the *best* way of doing it, but I do it in the same way as you did it. – adricadar May 07 '15 at 14:03