Sort list of objects in MVC - javascript

I am trying to build page that shows all selected movies depending on genre,
with $.post
If genre is not selected page should show all movies.It is default selection.
This is Controller code:
public class BrowseController : Controller
{
private MovieContext context = new MovieContext();
// GET: Browse
public ActionResult Index()
{
ViewBag.Genres = context.Genre.ToList();
IEnumerable<Movie> mov = TempData["movies"] as IEnumerable<Movie>;
if (mov == null)
{
IEnumerable<Movie> movies = context.Movies.ToList();
return View(movies);
}
return View(mov);
}
[HttpPost]
public ActionResult Index(int id = -1)
{
IEnumerable<Movie> model;
if (id != -1)
{
model = context.Movies.Where(x => x.GenreId == id);
}
else
{
model = context.Movies.ToList();
}
ViewBag.Genres = context.Genre.ToList();
TempData["movies"] = model;
return RedirectToAction("", "Browse");
}
}
And this is the view code:
#model IEnumerable<Movies.Models.Movie>
#using Movies.Models
#{
ViewBag.Title = "Index";
var Movie = Model.FirstOrDefault();
List<Genre> Genres = ViewBag.Genres;
}
#Html.DropDownListFor(m => Movie.GenreId, new SelectList(Genres, "Id",
"Name"), "")
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Rating)
</th>
<th>
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Rating)
</td>
<td></td>
</tr>
}
</table>
#section Scripts{
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script>
$('select#Movie_GenreId').on('change', function () {
var value = $(this).find(':selected').val();
var url = "/Browse/Index";
$.post(url, { id: value });
});
</script>
}
I checked Chrome Debugging tool and Network tab and I see in Preview tab of response that there are no errors and Get Browse/Index action is returning expected results but I don't see them in View. Not sure why.

You make a POST request , but you don't handle the response. For instance, you forget to update the DOM structure.
For doing this, you have to attach a callback function to the returned response.
$.post(url, { id: value },function(response){
//here is request response
});
Also, when you use AJAX, the purpose is to update DOM without refresh page to see the updates.
The solution is to return a JSON object with all the informations and then, handle them in the callback function of $.post method.

Related

Object Moved Here - RedirectToAction

Again, after tiresome attempts to solve this annoying issue, I am back here. I am experiencing an "Object moved here" on my view in my MVC5 application after some return RedirectToAction("Index", "Roles", model); action on my controller.
I have considered solutions from the following links:
RedirectToAction and "Object moved to here" error
ASP.NET MVC Website: Object Moved to Here
https://forums.asp.net/t/1643235.aspx?+Object+moved+to+here+problem
but none are applicable to my problem.
Before anyone marks this as a duplicate, please consider the scenario below:
But now the weird thing is that after I have clicked on the 'here' link and it now renders my view - it has a horizontal split screen showing the correct display of my view on top and below the view that throws an Http Error Code - in this case its Error Code 500 : Internal Server Error.
The reason why I am getting the http status code error is due to this unanswered question here (one of many) :
Failed to load resource: Uncaught TypeError: $(...).select2 is not a function
But that is besides the point right now.
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create([Bind(Include = "Name,Description")] ApplicationRole model)
{
try
{
if (ModelState.IsValid)
{
var role = new ApplicationRole()
{
Name = model.Name,
Description = model.Description
};
var roleManager = new RoleManager<ApplicationRole>(new RoleStore<ApplicationRole>(db));
var result = await roleManager.CreateAsync(role);
if (result.Succeeded)
{
return RedirectToAction("Index", "Roles", model);
}
else
{
AddErrors(result);
}
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
// If we got this far, something failed, redisplay form
return View(model);
}
//Below is my index method in my Roles controller which is the action that redirection needs to route to:
[Route("/Roles")]
public ActionResult Index()
{
if (TempData["StatusMessage"] != null)
{
ViewBag.StatusMessage = TempData["StatusMessage"].ToString();
}
else
{
ViewBag.StatusMessage = "";
}
var roles = db.Roles.ToList();
return View("Index", roles);
}
//GET method to create view
public ActionResult Create()
{
return View();
}
View:
#model IEnumerable<User_Manager_Interface.Models.ApplicationRole>
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
#if (ViewBag.StatusMessage != null)
{
if (ViewBag.StatusMessage != "")
{
string tmp = ViewBag.StatusMessage;
if (tmp.Contains("error"))
{
<div class="notification msgerror">
<a class="close"></a>
<p>#ViewBag.StatusMessage</p>
</div>
}
else
{
<div class="notification msgsuccess">
<a class="close"></a>
<p>#ViewBag.StatusMessage</p>
</div>
}
}
}
<br />
#Html.ActionLink("Create New", "Create", "Roles", new object { }, new { #class = "stdbtn" })
<br />
<br />
<div class="contenttitle radiusbottom0">
<h2 class="table"><span>Roles</span></h2>
</div>
<table cellpadding="0" cellspacing="0" border="0" class="stdtable" id="dyntable">
<colgroup>
<col class="con0" />
<col class="con1" />
<col class="con0" />
</colgroup>
<thead>
<tr>
<th class="head1">Name</th>
<th class="head0">Description</th>
<th class="head1">Options</th>
</tr>
</thead>
<tfoot>
<tr>
<th class="head1">Name</th>
<th class="head0">Description</th>
<th class="head1">Options</th>
</tr>
</tfoot>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
#Html.ActionLink("Details", "Details", new { id = item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id = item.Id })
</td>
</tr>
}
</tbody>
</table>
#section Scripts {
#Scripts.Render("~/bundles/tables")
}
Model:
public class ApplicationRole : IdentityRole
{
[Display(Name = "Description")]
[StringLength(100, MinimumLength = 5)]
public string Description { get; set; }
}
"Error" Controller:
public class ErrorController : Controller
{
//
// GET: /Error/
public ActionResult Index(int statusCode, Exception exception)
{
Response.StatusCode = statusCode;
return View();
}
}
"Error" View:
#{
ViewBag.Title = Response.StatusCode;
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2 style="visibility:hidden">#ViewBag.Title</h2>
<div class="errorWrapper">
<h2>An internal server error #ViewBag.Title has occurred</h2>
<h1 class="pageErrorTitle" style="color:red">Error #ViewBag.Title - Page Not Found</h1>
<h3 style="color:black">You may have clicked an expired link or mistyped the address.</h3>
<br />
<a class="default" href="javascript:history.back()">Back to Previous Page</a> <a class="default" href="http://localhost:53648">Return to Dashboard</a>
</div>
Please see screenshots for more visual clarity:
Update:
According to #Munzer 's answer below, I tried to change my Index action method to take in the model route value seeing as though I am passing it in my return statement. See below:
public async Task<ActionResult> Create(ApplicationRole model)
{
if (ModelState.IsValid)
{
var role = new ApplicationRole()
{
Name = model.Name,
Description = model.Description
};
var roleManager = new RoleManager<ApplicationRole>(new RoleStore<ApplicationRole>(db));
var result = await roleManager.CreateAsync(role);
if (result.Succeeded)
{
//return RedirectToAction("Index", "Roles", model);
return RedirectToAction("SuccessfullyAddedNewRole", "Roles", model);
}
else
{
AddErrors(result);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
public ActionResult SuccessfullyAddedNewRole(ApplicationRole model)
{
return View(model);
}
But the error still persists. I have tried everything I can think of.
I think the error is here
return RedirectToAction("Index", "Roles", model);
you are passing route values but your index action doesn't accept any, it generate the value itself, you can simple do this instead
return RedirectToAction("Index", "Roles");,
and your index will query the new model, if you want to pass the model, you need to edit your index action accordingly, to accept role model.
Solution can be found on this SO post of mine. Fixed everything :-)
GET http://localhost/Roles/Create 500 (Internal Server Error)

Reloading partial views and Ajax - ASP.NET MVC

I have an interesting problem while reloading partial views with ajax. I have a following setup in the master View:
<div>
<div id="items">
#Html.Partial("SubView", Model.Items);
</div>
<div>
SubView is generally a list of items in a table as follows:
<table class="table table-striped">
<tr>
<th>Date</th>
<th>Time</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
#Html.HiddenFor(modelItem => item.Id)
<td>#Html.DisplayFor(modelItem => item.Date)</td>
<td>#Html.DisplayFor(modelItem => item.Time)</td>
<td>
#Html.ActionLink("Delete", "Delete", new { itemId= item.Id, page = Model.PageNumber }, new { #class = "deleteItem" })
</td>
</tr>
}
DeleteItem Action in the controller does basically the following:
[HttpDelete]
public ActionResult DeleteItem(int itemId, int page)
{
this.dbService.DeletItem(expenseId);
return PartialView("SubView", this.GetPagedList(page));
}
In the script that I refer in the master View I have the following code:
$(document).ready(function () {
// delete expense
$(".deleteItem").click(function () {
$.ajax({
url: this.href,
type: 'delete',
success: function (result) {
$("#items").html(result);
}
});
return false;
});
This works fine the first time, but the second time it only loads the partial View -> since the JavaScript code is not being executed...
I am relatively new to that stuff and I am a bit confused what's going on here.
All 3rd party scripts are rendered in the Layout.cshtml
You can't attach a .click() event to a dynamically generated item. You have to structure it this way:
$(document).on('click', '.deleteItem', function() {
// Deletey stuff here.
});
For partial views to render, you have to make the return type PartialViewResult rather than ActionResult. Because ActionResult causes a redirection.
Try editing your DeleteItem function like this.
[HttpDelete]
public PartialViewResult DeleteItem(int itemId, int page)
{
this.dbService.DeletItem(expenseId);
return PartialView("SubView", this.GetPagedList(page));
}

Refreshing a Table in a Partial View

I am trying to make some blocks of code work from a blank MVC project (no authentication) before applying its logic to my actual project but I can't seem to do it right. I'm trying to have a table in a partial view to reload/refresh/update itself every certain span of time so it'll reflect any changes that was made and that happened in another webpage/browser.
The snippet that fires a function every few second work but the rendering/refreshing is where it gets trippy. I've been following this example with no luck (Refresh Partial View Div in MVC 5).
Here are my code:
View(Index.cshtml)
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<div id="peopletablediv">
#{ Html.RenderAction("Person");}
</div>
Partial View (Person.cshtml)
#model IEnumerable
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
#Html.ActionLink("Details", "Details", new { id = item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id = item.Id })
</td>
</tr>
}
</table>
Controller(PeopleController.cs)
public class PeopleController : Controller
{
private WebApplication1Context db = new WebApplication1Context();
// GET: People
public ActionResult Index()
{
return View();
}
public ActionResult Person()
{
return PartialView(db.People.ToList());
}
}
JavaScript(within the index.cshtml only since I'm just testing)
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript">
$(document).ready(function () {
var url = '#Url.Action("Person")';
var div = $("#peopletablediv");
setInterval(function () {
div.load(url);
}, 2000);
});
</script>
I've only a few months experience in asp.net MVC and web development in general. Which part would I be getting wrong here?

Getting a NULL value back for a Model when I see it is NOT NULL during debugging

I have a "Details" View that I am displaying to the user to find out if any statuses are associated with any projects.
When the "GET" for the "Details" view is performed, only a dropdownlist appears asking the user to select an item from the list. In the View, I simply check if the "Model" is null to display the rest of the view or not (the associated projects for that status).
During the "POST", a "status" is retrieved with its associated 'projects'. While coming back into the View, I am expecting the Model not to be null (since it found a status and its associated projects).
If the Model is not null, I want to display the rest of the View.
In the "POST", why is the Model still null? See below code & screenshots. Please copy and paste the screenshot to your favorite image viewer for better viewing.
fyi, after looking in the browser with the debugging tool, I can see that there is no html displayed after the dropdownlist?????
Model
namespace YeagerTechDB.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
[Serializable, DataContract(IsReference = true)]
public partial class Status
{
public Status()
{
Projects = new HashSet<Project>();
}
[Key]
[ScaffoldColumn(true)]
[DataMember]
public short StatusID { get; set; }
[Required]
[StringLength(30)]
[Display(Name = "Status")]
[DataMember]
public string StatusDescription { get; set; }
[DataMember]
public virtual ICollection<Project> Projects { get; set; }
}
}
JS
$.ajax({
url: Url,
data: JSON.stringify(status_Input),
//data: AddAntiCSRFToken(JSON.stringify(status_Input)),
dataType: "html",
type: "POST",
contentType: "application/json; charset=utf-8",
async: true,
beforeSend: function ()
{
$('<div id="divLoadMsg" style="text-align:center"><img src="~/Content/progress.gif" /><br/><b>Please wait...</b></div>').dialog({
modal: true, resizable: false, height: 'auto', width: 'auto', minHeight: '30px',
open: function () { $('.ui-dialog-titlebar').hide(); }, close: function () { $('.ui-dialog-titlebar').show(); $(this).dialog('destroy').remove() }
});
},
success: function (data, status)
{
if (status == "success")
{
// Retrieved data
}
},
CONTROLLER
// GET: Statuses/StatusProjects/Details
public ActionResult Details()
{
return View();
}
// POST: Statuses/StatusProjects/Details/5
[HttpPost]
public async Task<ActionResult> Details(short? id)
{
if (id == null)
{
return View("IDIsNull");
}
Status status = await db.GetProjectsByStatusIDAsync(id);
if (status == null)
{
return View("ObjectModelNull");
}
return View();
}
VIEW
#model YeagerTechDB.Models.Status
#using YeagerTechDB.ViewModels.Statuses
#{
ViewBag.Title = "Statuses";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h3>Select Status to see associated Projects</h3>
<div>
#Html.Partial("_SelectStatusProjects", new StatusesDDL());
</div>
#if (Model != null) // Needed for GET
{
<div>
<table class="table table-condensed">
<tr>
<th>
Associated Projects for selected Status
</th>
<th></th>
</tr>
<tr>
<th align="right">Project ID</th>
<th>Project Description</th>
<th>Project Name</th>
<th align="right">Quote</th>
<th>Notes</th>
<th>Created Date</th>
<th>Updated Date</th>
</tr>
<tbody>
#foreach (var item in Model.Projects)
{
<tr>
<td align="right">
#Html.DisplayFor(m => item.ProjectID)
</td>
<td>
#Html.DisplayFor(m => item.Description)
</td>
<td>
#Html.DisplayFor(m => item.Name)
</td>
<td align="right">
#Html.DisplayFor(m => item.Quote)
</td>
<td>
#Html.DisplayFor(m => item.Notes)
</td>
<td>
#Html.DisplayFor(m => item.CreatedDate)
</td>
<td>
#Html.DisplayFor(m => item.UpdatedDate)
</td>
</tr>
}
</tbody>
</table>
</div>
}
EDIT
After making the change that Kundan suggested, I can tell during debugging, if I step through the code, it goes into the View after the POST. The Model is not null and it then properly cycles through the child records that I want displayed on the screen.
However, after that is finished, those records are not displayed on the browser window! The only thing that appears is the dropdownlist again without any display beneath that.
Nothing else is executed after the debugging of the View on the POST which is correct.
The only change that was made in this process is returning the object model of the View (status) as Kundan suggested.
How come the records are not being displayed in the browser after the POST?
fyi, after looking in the browser with the debugging tool, I can see that there is no html displayed after the dropdownlist?????
fyi, I also tried running the page without the dropdownlist and forcing in a value during debugging which would bring back some projects, the same way as if I had selected it from the drop down list. Even with the html removed for the dropdownlist, it went through the View cycled through the collection, but did not emit any html?
Here are the screen shots...
The Model is null because you didn't pass back it to View from your controller. The code should be like below:
[HttpPost]
public async Task<ActionResult> Details(short? id)
{
if (id == null)
{
return View("IDIsNull");
}
Status status = await db.GetProjectsByStatusIDAsync(id);
if (status == null)
{
return View("ObjectModelNull");
}
return View(status);
}
This will fix your issue.

Open Dialog when drop down was changed

I am trying to open a pop up (some dialog) when the user changes the drop down list from the default value which is male to female.I used the JS code from a previous post but nothing happens, in the inspect element I get message that tells me there is no dialog, any idea how to make it work?
I've also tried with an alert but nothing happens either when I change the selection in the drop down list...
I'm very new to JS and Jquery ...
public class Ad
{
public int Name { get; set; }
public string Email { get; set; }
public IEnumerable<SelectListItem> Gender
{
get
{
return new[]
{
new SelectListItem {Value = "M", Text = "Male"},
new SelectListItem {Value = "F", Text = "Female"}
};
}
}
The Index.cshtml code.
#model IEnumerable<Ad.Models.Ad>
<script src='https://code.jquery.com/jquery-1.11.0.min.js'></script>
<script src='https://code.jquery.com/ui/1.9.2/jquery-ui.min.js'></script>
<script type="text/javascript">
$(document).ready(function () {
$('#M').change(function () {
if ($(this).val() === "F") {
alert("I am an alert box!");
dialog.dialog('open');
}
});
});
</script>
<h3>My APP</h3>
p>
#using (Html.BeginForm())
{
}
#*<br style="margin-bottom:240px;" />*#
#Html.ActionLink("Create", "Create",
null, htmlAttributes: new { #class = "mybtn" })
<p>
</p>
<style type="text/css">
a.mybtn {
background: #fa0088;
}
</style>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Email)
</th>
<th>
#Html.DisplayNameFor(model => model.Gender)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Email)
</td>
<td>
#Html.DropDownListFor(modelItem => item.Geneder, item.Gender, new { id = "M" })
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.ID }) |
#Html.ActionLink("Details", "Details", new { id = item.ID }) |
#Html.ActionLink("Delete", "Delete", new { id = item.ID })
</td>
</tr>
Normally the problem occurs when there is no div with an id as 'dialog'. The javascript variable should be initialized as dialog = $('#dialog')
<script type="text/javascript">
$(document).ready(function () {
$("#M").change(function () {
alert($(this).val());
alert($(this).val() == "F");
if ($(this).val() == "F") {
alert("I am an alert box!");
//dialog.dialog('open'); //commenting out this line would tell where the problem lies.
}
});
});
</script>
update: To make it applied to the multiple select boxes, you should use class selector eg .M of jQuery instead of id selector #M. For that first we need to give same class M all the select boxes.
#Html.DropDownListFor(modelItem => item.Geneder, item.Gender, new { id = "M", #class = "M" })
Now change $("#M").change(function () { to $(".M").change(function () {.
$('#M') replace with $('select')

Categories

Resources