Ajax missunderstanding, or an error? - asp.net-mvc

Can you please explain me how should i use Ajax properly.
I have an easy example in Asp.Net MVC:
This is my layout view
<html>
<head>
//scripts
</head>
<body>
<div id="header">
<div class="logo">
<img id="LogoImg" src="http://www.ruralcomshow.com/wpontent/uploads/2014/06/Midwest-Data-Center-Logo-175x75.png" />
</div>
</div>
<div class="wrapper">
<div class="left-side">
//some navigation
</div>
<div id="right-side">
#RenderBody()
</div>
</div>
<div id="footer">
<div class="clearfix">
//some footer
</div>
</div>
</body>
</html>
This is my controller:
public class HomeController : Controller
{
public PartialViewResult Ajax()
{
return PartialView();
}
public ActionResult Index()
{
return View();
}
}
This is Ajax partial view:
<h2>This is how it's done</h2>
#Html.ActionLink("back :C","Index","Home")
This is Index view:
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#Ajax.ActionLink("Go, go Ajax!", "Ajax", "Home", new AjaxOptions { UpdateTargetId = "right-side", InsertionMode = InsertionMode.Replace})
So, as I understood when i click Ajax ActionLink my whole page should not rerender, and the only thing that should change is div with id "right-side"? So the problem is that the whole page always gets rerendered.
Am I doing something wrong? Or is this a problem of my understanding?

Include jquery and unobtrusive-ajax at the bottom of the page as shown :-
</footer>
#Scripts.Render("~/bundles/jquery")
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
#RenderSection("scripts", required: false)
</body>
</html>

Related

(MVC) I have a search bar in my shared _Layout. It works from other Views but not in the _Layout

Basically what the title says. I have a view named books in which the search bar works perfectly and gives results. This is not happening in the _Layout shared view. I've tried several scripts and stuff but to no avail. Any advice?
This is the _Layout
<!DOCTYPE html>
#model IEnumerable<GoodReads.Models.Libro>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title</title>
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
#Html.ActionLink("Nombre de aplicación", "Index", "Home", new { area = "" }, new { #class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>#Html.ActionLink("Inicio", "Index", "Home")</li>
<li>#Html.ActionLink("Registrar Turno", "AltaTurno", "Turno")</li>
<li>#Html.ActionLink("Buscar Libros", "Books", "Libro")</li>
<li>
#using (Html.BeginForm(FormMethod.Get))
{
<div>
#Html.TextBox("parametro")
<input type="submit" id="btnSearch" value="Some text"/>
</div>
}
</li>
</ul>
</div>
</div>
</div>
<div id="Books">
</div>
<div class="container body-content">
#RenderBody()
<hr />
<footer></footer>
</div>
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/bootstrap")
#RenderSection("scripts", required: false)
</body>
</html>
This is the Books view
#model IEnumerable<GoodReads.Models.Libro>
#{
/**/
ViewBag.Title = "Books";
}
<head>
<link href="#Url.Content("~/Content/Style.css")" rel="stylesheet" type="text/css" />
</head>
<body>
#foreach (var item in Model)
{
<div style="margin-left: 350px; margin-top: 50px;">
<h1 class="title-font">
#item.Title
<small class="year-font">(#item.Year)</small>
</h1>
</div>
<div style="margin-left: 350px; margin-top: 10px;">
<p style="font-size: 22px;">by #item.Author</p>
</div>
<div style="margin-left: 350px; margin-top: 10px;">
<p style="font-size: 22px;">#item.ISBN</p>
</div>
}
</body>
The Controller for Books (The conection to the database is made through instead of doing it directly in the controller)
// GET: Libro
public ActionResult Index()
{
return View();
}
public ActionResult Books(string parametro)
{
List<Libro> listalibros = ADLibros.BuscarLibro(parametro);
return View(listalibros);
}
The problem is your form. You don't set its action. If you don't tell it it will use the default which is the controller that renders the page. So when your Books controller renders the page this works because the default controller will be the books controller. You need to specify the action of your get form explicitly. To see the problem use your browser developer tools to inspect the form for the books page and the other pages.
To fix (assuming your controller for books is called BooksController) change the form code in your _Layout page to this
#using (Html.BeginForm("books", "books", FormMethod.Get))
{
<div>
#Html.TextBox("parametro")
<input type="submit" id="btnSearch" value="Some text" />
</div>
}
We are using an overload of Html.BeginForm with 3 arguments. The first is the actionName, the second is the controllerName and the 3rd is the FormMethod.

Is it possible to display multiple partial view one below row-wise in single _Layout.cshtml?

I have a situation where i wish to render 2 partial views in single layout.cshtml one below another. Each partial view belongs to separate controller. I processed it using 2 different approach, the first one which i wanted it to work didn't worked out.
What i wanted it is to have partial view controller of categoris1 (see div-id below in layout.cshtml) and then below it display partial view of categoris2 div.
let's say this is my _Layout.cshtml
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title - ABCD</title>
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
<link href="~/Content/bootstrap-theme.min.css" rel="stylesheet" />
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
#Html.ActionLink("TitleName", "Index", "Files", new { area = "" }, new { #class = "navbar-brand" })
</div>
</div>
</div>
<div class="row panel">
//My first view should be displayed here
<div id="categoris1" class="col-lg-3">
#Html.Action("DispatchedProducts", "DispatchedProducts")
</div>
//Second view should be displayed here just below first one
<div id="categoris2" class="col-lg-3">
#Html.Action("DisplayUnDispatchedProducts", "UnDispatchedProducts")
</div>
<div class="col-lg-8">
#RenderBody()
</div>
<hr />
<footer>
<p>© #DateTime.Now.Year - My MVC Application</p>
</footer>
</div>
</body>
</html>
This results in displaying of the categoris1 div controller view only when i run application (but not categoris2 partialview)and categoris2 div partial view is displayed at other url (when i write path to controller and view in browser) and what i wanted it is to display on same page just below categoris1 .
My next approach which worked was i just kept this categoris2 div (line below) in the partial view of 'DispatchedProducts' at the bottom of DisplayDispatchedProducts.cshtml and it displayed exactly what i expected.
<div id="categoris2" class="col-lg-3">
#Html.Action("DisplayUnDispatchedProducts", "UnDispatchedProducts")
</div>
Complete DisplayDispatchedProducts.cshtml something like this:
#model IList<ABC.Models.Product>
#{
ViewBag.Title = "First view";
}
<div class="col-md-10">
<h2>Dispatched Items</h2>
<div class="form-group">
<label class="col-md-2 control-label">Dispatched Items</label>
<table>
#foreach (var item in Model)
{
<tc>
<td>
<img src=#item.ProdUrl height="100" width="100" />
</td>
</tc>
}
<hr />
</table>
</div>
</div>
and DisplayDispatchedProducts controller has method like this (similar is other controller and partial view with same return types but different queries) :
public PartialViewResult DisplayDispatchedProducts()
{
productDispatched = uow.ProductsRepository.GetProductWithOrder().ToList();
return PartialView(productDispatched);
}
But i want to move with the first approach to have call to both partial views in just _Layout.cshtml file like i mentioned above. Which i expected to display both in a row below each other. Is it feasible to happen ? How to make it work ?
Please let me know if any other info needed
Have you tried calling Html.RenderPartial or Html.RenderAction?
RenderPartial(String partialViewName)
RenderAction(String actionName, String controllerName, Object routeValue)
There are other overrides for each of these methods depending on which version of the framework you are using.

Controller to View via ViewData

This is View File here Displaying error for student in list
#model IEnumerable<Controller2View.Models.Students>
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div class="container">
<div class="btn btn-default">
<ul class="list-group">
#foreach (var std in ViewData["StudentData"] as List<Students>)
{
<li class="list-unstyled">
std.StudentName
</li>
}
</ul>
</div>
</div>
</body>
</html>
This is Controller file which have a list defined and viewdata for transferring data from controler to View. Model also defined well but dont know whu its not working.
public ActionResult Index()
{
List<Students> studentList = new List<Students>() {
new Students(){ StudentId=1, StudentName="Steve"},
new Students(){ StudentId=2, StudentName="Bill"},
new Students(){ StudentId=3, StudentName="Ram"}
};
ViewData["StudentData"] = studentList;
return View(studentList);
}
Would be good to know what exactly is not working. But still 2 things:
Either use the view with a model or with ViewData.
I guess you get a list of 3 items with "std.StudentName", that's because it must read #std.StudentName
Use below code in controller
public ActionResult Index()
{
var studentList = new List<Students>() {
new Students(){ StudentId=1, StudentName="Steve"},
new Students(){ StudentId=2, StudentName="Bill"},
new Students(){ StudentId=3, StudentName="Ram"}
};
return View(studentList);
}
Now, In View use below code
#model IEnumerable<Controller2View.Models.Students>
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div class="container">
<div class="btn btn-default">
<ul class="list-group">
#foreach (var std in Model)
{
<li class="list-unstyled">
std.StudentName
</li>
}
</ul>
</div>
</div>
</body>
</html>
Hopefully it will works as I am using model directly instead of casting it into list.

Validation in Partial View not working in MVC 4

I have a #Html.ValidationMessageFor(model => model.FirstName) in Partial view that is not functioning properly. The text box's contained within the loaded Partial View have the "Required" Data Annotation on them and the associated message displays right away. How can I avoid this? It doesn't even validate.
Partial View Code
#{ Html.EnableClientValidation(); }
#*#{ ViewContext.FormContext = new FormContext(); }*#
#using (Html.BeginForm("ActionName", "ControllerName"))
{
<div>
#Html.TextBoxFor(model => model.FirstName)
#Html.ValidationMessageFor(model => model.FirstName)
</div>
....//some more HTML
}
Main View Code
<div class="modal" id="modalId" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
</div>
<div class="modal-body" id="modalbodyId">
#Html.Partial("PartilViewName")
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>
I have tried the following things so far.
1. Added the following line of code in Partial View
#{ ViewContext.FormContext = new FormContext(); }
2.Both ClientValidationEnabled and UnobtrusiveJavaScriptEnabled are set to true in web.config
3.Added the following script tags in BundleConfig.cs
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
In all the posts that I have seen I need to use an AJAX call like the below code.
However I am not sure on how to use it.
$("#create").click(function () {
var form = $("#create_person").closest("form");
form.removeData('validator');
form.removeData('unobtrusiveValidation');
$.validator.unobtrusive.parse(form);
$.ajax({
url: "/Person/CreateOrUpdate",
type: "POST",
data: $("#create_person").serialize(),
cache: false
});
});
Code Courtsey
Try adding the model you use for your partial view as a property in the model of the view the partial is created in.
public class MainViewModel
{
// properties
public PartialViewModel PartialVm { get; set; }
}
Then when you render your partial, pass it the PartialViewModel property.
#Html.Partial("PartialViewName", Model.PartialVm)

Jquery mobile dialog return in MVC post action

I am using JQuery Mobile 1.4 and MVC 4 to test dialog. But I don’t know what should be returned in dialog post action.
There are two questions:
1. What should be returned for dialog action
2. The input data in master page will be lost after dialog post
Master page View Code:
#model MvcApplication4.Models.ViewModel
#{
Layout = null;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>TestDialog</title>
<meta name="viewport" content="width=device-width" />
<link href="/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<link href="/Content/site.css" rel="stylesheet"/>
<link href="/Content/jquery.mobile-1.4.0-beta.1.css" rel="stylesheet" />
<script src="/Scripts/modernizr-2.6.2.js"></script>
<script src="/Scripts/jquery-2.0.3.js"></script>
<script src="/Scripts/jquery-ui-1.10.3.js"></script>
<script src="/Scripts/jquery.mobile-1.4.0-beta.1.js"></script>
</head>
<body>
<div id="layoutPage" data-role="page" data-theme="a">
<div id="layoutHeader" data-role="header">
<h2>TestDialog</h2>
</div>
<div id="layoutContent" data-role="content">
#using (Html.BeginForm())
{
<div>
<div class="editor-label">
#Html.LabelFor(model => model.IDDocument)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.IDDocument)
#Html.ValidationMessageFor(model => model.IDDocument)
</div>
</div>
<div data-role="controlgroup" data-type="horizontal" data-mini="true">
<a id="addDetail" href="#Url.Action("ShowDialog", "SampleTest")" data-rel="dialog" data-role="button" >Test dialog</a>
</div>
}
</div>
</div>
<script>
$(document).on("mobileinit", function () {
$.mobile.ajaxEnabled = false;
});
</script>
</body>
</html>
Dialog View Code:
#model MvcApplication4.Models.ViewModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>DialogView</title>
</head>
<body>
<div id="detailPage1" data-role="dialog" >
#using (Html.BeginForm("ShowDialogActioinPost", "SampleTest", FormMethod.Post))
{
<div data-role="header">
<button type="submit" data-icon="check" class="ui-submit" data-inline="true" data-mini="true">Save</button>
<h2 >Dialog Information</h2>
<a data-rel="back" data-icon="back">Go back</a>
</div> //end header
<div data-role="content">
<div class="editor-label">
#Html.LabelFor(model => model.SeqNo)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.SeqNo)
#Html.ValidationMessageFor(model => model.SeqNo)
</div>
</div>
}
</div>
</body>
</html>
Controller Code:
[HttpGet]
public ActionResult ShowDialog()
{
return View("DialogView");
}
[HttpPost]
public ActionResult ShowDialogActioinPost(ViewModel vm)
{
return View("Index"); // should return to master page, but it doesn't work
}
Thanks
Wilson
Try RedirectToAction("Index"); instead of View("Index");
You have to return the model to your master page.
[HttpPost]
public ActionResult ShowDialogActioinPost(ViewModel vm)
{
return View("Index", vm);
}
The answer is here.
Thanks
Wilson

Resources