0

I have a page which has a list of Students. The partial view which renders a list is called "StudentManager". The partial view which I use in a modal to create a new student is called "NewStudent".

I have a couple of issues going on with this controller code. For some reason, after I press submit on the "NewStudent" partial view, every time afterwards that I refresh the page a new student is there without me going in and pressing submit... This is a problem.

Also, I have searched similar topics here on stack and I cannot seem to understand why return PartialView("StudentManager",db.Students.ToList()); will not automatically refresh my "StudentManager" view. This code is supposed to give me a list in one partial view, and another partial view is supposed to let me create a new list item and then tell the list partial view to update.

Controller:

public ViewResult Index()
    {
            return View();
    }
public ActionResult StudentManager()
    {
        return PartialView(db.Students.ToList());
    }
public ActionResult NewStudent()
    {
    return PartialView();
    }
//
// POST: 
[HttpPost]
public ActionResult NewStudent(Student student)
{
    if (ModelState.IsValid)
    {
        db.Students.Add(student);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return PartialView();
}

Index.cshtml:

@Html.Action("StudentManager", "StudentController")
<div class="modal modal-wide fade" id="myModal4" role="dialog">
    <div class="modal-dialog">
        @Html.Action("NewStudent", "StudentController")
    </div>
</div>

Here is the "NewStudent.cshtml" view:

@model GunneryTracker.Models.Student
    <fieldset>
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal">&times;</button>
                <center>
                    <h4 class="modal-title">New Student</h4>
                </center>
            </div>
            <div class="modal-body">
                <div class="col-md-12">
                    <div class="clearfix"></div>
                    <div class="x_content">
                        <br />
                        <form class="form-horizontal form-label-left" >
                            <div class="form-group">
                                <div class="col-md-6 col-sm-6 col-xs-12">
                                    <label class="control-label col-md-2 col-sm-2 col-xs-12" style="margin-right:10px">Course</label>
                                    <div class="col-md-3  col-sm-3 col-xs-12">
                                        @Html.DropDownList("CourseID", null, "-- Select Course --", htmlAttributes: new { @class = "form-control" })
                                        @Html.ValidationMessageFor(model => model.CourseID, "", new { @class = "text-danger" })
                                    </div>
                                    <label class="control-label col-md-2 col-sm-2 col-xs-12" style="margin-right:10px">Location</label>
                                    <div class="col-md-3 col-sm-3 col-xs-12">
                                        @Html.DropDownList("LocationID", null, "-- Select Location--", htmlAttributes: new { @class = "form-control" })
                                        @Html.ValidationMessageFor(model => model.LocationID, "", new { @class = "text-danger" })
                                    </div>
                                </div>
                                <div class="editor-label">
            @Html.LabelFor(model => model.FName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.FName)
            @Html.ValidationMessageFor(model => model.FName)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.LName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.LName)
            @Html.ValidationMessageFor(model => model.LName)
        </div>
                            </div>
                            <br />
                            <br />
                            <div class="form-group">
                                <center>
                                    <p>
                                        <input type="submit" value="Create" />
                                    </p>
                                </center>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Save</button>
            </div>
        </div>
    </fieldset>

Pardon the slouchy html... The prettyfication isnt completed...

2 Answers2

1

Answer to 2nd question(if I understood what you meant):

It's not that smart as you expected. After POST better to send back JSON result or simple null if don't use Ajax.

I would suggest you after POST do return RedirectToAction("Index"); Then page auto refresh students list.

Or do your POST via $.ajax and on success update student list using jquery or js

here is how I'm usually do it for simple "admin page" forms.

    public ActionResult Teams()
    {
        var list = _data.GetTeams(true);
        return View(list);
    }

    public ActionResult TeamCreate()
    {
        var model = _data.GetTeamCRUDViewModel();
        return PartialView("_TeamCreate",model);
    }


    [HttpPost]
    public ActionResult TeamCreate(TeamCRUDViewModel model)
    {
        _data.SaveTeam(model);
        return RedirectToAction("Teams");
    }

But on customer UI I would recommended to use $.ajax post. Update: Ok I see your issue

@model Student
<fieldset>
<div class="modal-content">
    <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal">&times;       </button>
        <center>
            <h4 class="modal-title">New Student</h4>
        </center>
    </div>
    <div class="modal-body">
        <div class="col-md-12">
            <div class="clearfix"></div>
            <div class="x_content">
                <br />
             @using (@Html.BeginForm("NewStudent", "Home", FormMethod.Post))
             {
                 <div class="form-group">
                     <div class="col-md-6 col-sm-6 col-xs-12">
                         <label class="control-label col-md-2 col-sm-2 col-xs-12" style="margin-right: 10px">Course</label>
                         <div class="col-md-3  col-sm-3 col-xs-12">
                             @Html.DropDownList("CourseID", null, "-- Select Course --", htmlAttributes: new { @class = "form-control" })
                                @Html.ValidationMessageFor(model => model.CourseID, "", new { @class = "text-danger" })
                         </div>
                         <label class="control-label col-md-2 col-sm-2 col-xs-12" style="margin-right: 10px">Location</label>
                         <div class="col-md-3 col-sm-3 col-xs-12">
                             @Html.DropDownList("LocationID", null, "-- Select Location--", htmlAttributes: new { @class = "form-control" })
                                @Html.ValidationMessageFor(model => model.LocationID, "", new { @class = "text-danger" })
                         </div>
                     </div>
                     <div class="editor-label">
                         @Html.LabelFor(model => model.FName)
                     </div>
                     <div class="editor-field">
                         @Html.EditorFor(model => model.FName)
                         @Html.ValidationMessageFor(model => model.FName)
                     </div>
                     <div class="editor-label">
                         @Html.LabelFor(model => model.LName)
                     </div>
                     <div class="editor-field">
                         @Html.EditorFor(model => model.LName)
                         @Html.ValidationMessageFor(model => model.LName)
                     </div>
                 </div>
                 <br/>
                 <br/>
                 <div class="form-group">
                     <center>
                         <p>
                             <input type="submit" value="Create"/>
                         </p>
                     </center>
                 </div>
             }
            </div>
        </div>
    </div>
    <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Save</button>
    </div>
</div>

Also change

@Html.Action("StudentManager", "StudentController") to @Html.Action("StudentManager", "Student")

like if should be name of controller

Aleksei
  • 1,107
  • 9
  • 13
  • 1
    What is the difference in what I put? @Html.Action("NewStudent", "StudentController") Do they not do the same thing? –  Nov 03 '16 at 12:32
  • sorry I miss understand you. They are sort of same – Aleksei Nov 03 '16 at 12:36
  • That will not work though. The CreateStudent post action is of a partialView and Child actions are not allowed to perform redirect actions. –  Nov 03 '16 at 12:49
  • it will if you using on modal view form and submit, cause it will standard post, so you could do redirect. it's doesn't matter where from post action was called. Partial view it's just part of page, it's not a "child". I have 100s examples that it's works – Aleksei Nov 03 '16 at 12:55
  • I updated my code to what I believe you are saying, is what I put in the post method what you mean? –  Nov 03 '16 at 13:14
  • Yes, that what I meant, just part after if(){} bit useless. So it didn't reload page with refreshed student list? – Aleksei Nov 03 '16 at 13:20
  • Correct. It gives me the error with the above code. –  Nov 03 '16 at 13:41
  • well something wrong with your views. Cause I just played with it on my project and had no issue with redirecting public ActionResult testpost() { return PartialView("_test"); } [HttpPost] public ActionResult testpost(Model model) { return RedirectToAction("Index","AdminPanel"); } on index view: @Html.Action("testpost"); partial view: @using (Html.BeginForm("testpost", "Admin", FormMethod.Post)) { } – Aleksei Nov 03 '16 at 13:57
  • I posted the view in my question at the bottom. –  Nov 03 '16 at 14:06
  • see my update. you not specified form. here is link to project https://github.com/kogot/PartialRedirect.git just in case – Aleksei Nov 03 '16 at 15:00
  • Good answer. It helped me find my way. The key that I needed was that When I was calling the .partial, I needed to include using (Html.BeginForm("NewGunnery", "MasterGunner", FormMethod.Post, new { id = "newGunnery"})) { } to call the post, The reason that it was breaking was because I was using an action to call a partialView then to get to the page. simply removing the navigation action and calling it a partial and using the code I placed in the comment solved the whole 14 hour long headache... Thanks a ton for your help. The same goes to @Chris Pratt –  Nov 03 '16 at 15:11
1

There's a fundamental misunderstanding here about how things work. A client makes a request to a server and the server returns a response. The client, then, generally does something with that response. In the case of a web browser, it clears the current view in the tab/window, parses the response and renders it into that tab/window. There's actually a lot more that goes on, but I'm trying to keep it simplistic.

However, AJAX (or specifically the XMLHttpRequest object in JavaScript) is what you would call a thin client. It's like a little web browser within your web browser, only without all the bells and whistles. All it does is submit requests and deliver the response to a callback. That callback is a JavaScript function whose job is to do something with the response. If the goal is to replace some portion of HTML on the page, the JavaScript code in the callback must do that. It does not happen automatically.

It's also important to realize that a "partial view" is only a thing server-side. Whether MVC is returning a partial view, a normal view, or even a view composed from various partial views is all inconsequential. What the server returns to the client is just an HTML document. In the case of the client being a web browser, it then parses that HTML document and builds what's called the Document Object Model, or DOM. It then uses the DOM to "render" the page as formatted images and text.

Likewise, all an AJAX request returns is an HTML document, which is itself really just a text document with a mime type of "text/html" that informs the client that it should be treated as HTML. As I said, it's the job of the AJAX callback to do something with this response from the server, but the point here is that you can't just say "replace that partial with this HTML", because the concept of partials doesn't exist client side. All you have is a object graph (the DOM), and you must select something from the DOM and then insert the HTML into that.

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • 1
    That is not what I am 100% following. Given that partials are 100% server side, why then, when I submit the post to redirect to the index such as @Aleksei suggested, it gives me the "Child actions are not allowed to perform redirect actions" error? How does it know that the post is not that of the index? is it because the name of the function does not match the current URL? If that is the issue, then how do I get around it? –  Nov 03 '16 at 13:32
  • I just google for that error. Maybe if you change your Html.Action to Html.RenderAction it will fix it. Cause RenderAction return "proper" html – Aleksei Nov 03 '16 at 13:39
  • The error is coming from the MVC machinery. When you render a child action, although it's handled *like* an action, it's outside of the main request. You cannot redirect from a child action because it's not the actual request being handled. It's just MVC doing something as part of rendering a view. – Chris Pratt Nov 03 '16 at 13:46
  • 1
    So the reason behind HAVING to use an ajax request is to bypass the MVC machinery? –  Nov 03 '16 at 14:16
  • 1
    No. An AJAX request is just a request. Any request, AJAX or not, goes through IIS, and if it's not for a static file, is passed off to MVC for fulfillment. The point is that a child action is *not* a request. MVC, in it's implementation of child actions, follows the process that a request for an actual action would go through, but the child action itself is not part of the request pipeline. It's just something MVC is doing as part of rendering the view, and might as well just be invoking any random function. You can't redirect because the child action is not in control of the actual request. – Chris Pratt Nov 03 '16 at 16:00