I'm using C# asp.net mvc4 and trying to do ajax search. But ther is error and it says " The resource cannot be found.".
What I'm doing wrong?
Controller
//Search
[HttpPost]
public ActionResult ContractSearch(string Name)
{
var contracts = db.Contracts.Include(c => c.DocType).Include(c => c.CreditType).Include(c => c.Bank).Include(c => c.UserProfile).Where(c => c.FirstName.Equals(Name));
return View(contracts.ToList());
}
View
#model IEnumerable<CreditoriyaApp.Models.Contract>
#{
ViewBag.Title = "Index";
}
<div>
#using (Ajax.BeginForm("ContractSearch", "Contract", new AjaxOptions { UpdateTargetId = "searchresults" }))
{
<input type="text" name="Name" />
<input type="submit" value="Search" />
}
<div id="searchresults">
#if (Model != null && Model.Count()>0)
{
<ul>
#foreach (var item in Model)
{
<li>#item.FirstName</li>
}
</ul>
}
</div>
Error
Server Error in '/' Application.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /Contract/ContractSearch
Add the below in your controller. Then your error will be corrected.
public ActionResult ContractSearch()
{
return View();
}
for searching you can try something like below example.
Model:
public class Person
{
public string Name { get; set; }
public string Country { get; set; }
}
Controller:
public ActionResult SearchPerson()
{
return View();
}
[HttpPost]
public ActionResult SearchPerson(string searchString)
{
System.Collections.Generic.List<Person> lst = new List<Person>();
lst.Add(new Person { Name = "chamara", Country = "Sri Lanka" });
lst.Add(new Person { Name = "Arun", Country = "India" });
if (!string.IsNullOrEmpty(searchString))
{
lst = lst.AsEnumerable().Where(r => r.Name.Contains(searchString)).ToList();
}
string result = string.Empty;
result = "<p>Search Result<p>";
foreach (Person item in lst)
{
result = result + "<p> Names is: " + item.Name + " and Country is:" + item.Country + "<p>";
}
return Content(result, "text/html");
}
View:
#model IEnumerable<Mvc4Test.Models.Person>
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>SearchPerson</title>
<script src="#Url.Content("~/Scripts/jquery-1.7.1.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
</head>
<body>
#using (Ajax.BeginForm("SearchPerson", "Search", new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "searchresults" }))
{
#Html.TextBox("searchString")
<input type="submit" value="Search" />
}
<div id="searchresults">
</div>
</body>
</html>
Related
It redirects to whole new page instead of just updating the current one, I have unobtrusive scripts and web.config stuff. Why is this not working?
<div id="preview-image-placeholder"></div>
#foreach (var item in Model)
{
using (Ajax.BeginForm("PreviewImage/" + #item.Id.ToString(), "Music", null, new AjaxOptions { HttpMethod = "Post", InsertionMode = InsertionMode.Replace, UpdateTargetId = "preview-image-placeholder" },
new { #enctype = "multipart/form-data", #item.Id }))
{
#Html.AntiForgeryToken()
<input type="file" class="upload-image" id="upload-image-file_#item.Id" name="file" accept="image/*">
<button class="btn btn-default" id="btn-preview_#item.Id" style="display: none" type="submit"></button>
}
}
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
Controller:
[ValidateAntiForgeryToken]
[HttpPost]
public PartialViewResult PreviewImage(HttpPostedFileBase file, int id)
{
//Do other code stuff
return PartialView("_DisplayImage", song);
}
_DisplayImage partial view:
#model IEnumerable<MusicSite.Models.UploadedSong>
#using MusicSite.CustomHtmlHelpers;
#foreach(var item in Model)
{
if (#item.CoverImageBytes != null)
{
#Html.ImageFor(x => item.CoverImageBytes, #item.SongName + " Image", new { #id = "preview-image" })
}
}
Besides unobtrusive scripts you must add Microsoft Ajax libraries too (MicrosoftAjax.js and MicrosoftMvcAjax.js) so that Ajax.BeginForm works correctly.
Regards,
I have a partial view of saving email in newsletter mailing list that is used in Main partial view of the site. when click on its button, it should send form to services.js ,then send to action for saving in Database. But it saves "null" in it, when I set a break point on action, it doesn't go with it. what should i do?
Newsletter Model:
public class NewsletterModel
{
[Required(ErrorMessage = "Please enter your email address!")]
[Display(Name = "Email")]
public string Email { get; set; }
public Int16 LanguageId { get; set; }
}
partial view code:
#model Orinus.Models.NewsletterModel
<script src="#Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
<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>
<link href="../../Content/Default/Site.css" rel="stylesheet" type="text/css" />
<script src="../../Scripts/Services.js" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<div class="editor-label">
#Html.LabelFor(model => model.Email)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Email)
#Html.ValidationMessageFor(model => model.Email)
</div>
<br />
<p>
<input type="button" value="Register" id="saveEmailNewsletter" class="ButtonStyle"/>
</p>
}
This is the action code:
[HttpPost]
public ActionResult Index(NewsletterModel newsLetter)
{
if (!ModelState.IsValid)
{
return PartialView("_Newsletter", newsLetter);
}
SaveEmailForNewsletterSrv newsLetterSrv = new SaveEmailForNewsletterSrv();
newsLetterSrv.SaveEmailForNewsletter(newsLetter);
return Json(new { success = true });
}
}
this code is for Services.js:
/// <reference path="jquery-1.7.1.min.js" />
$(function () {
$("#saveEmailNewsletter").click(function () {
var email = $("#Email").val();
var language = 1;
newsLetter = { 'Email': email,'Language': language };
if (dat == null) {
alert("Please enter your email address!");
return;
}
$.ajax({
url: '/Newsletter/Index',
type: 'POST',
dataType: 'json',
data: newsLetter,
contentType: 'application/json; charset=utf-8',
success: function (result) {
if (result.success) {
// We have a JSON object in case of success
Alert ('Successfully registered...');
} else {
// We have the partial with errors in case of failure
// so all we have to do is update the DOM
$('#resultMessage').dialog(result);
}
}
});
})
});
EDIT
My Ajax form gets correct Id to update a content and a replace option.
Submitting is by clicking <input type="submit" value="submit!" />.
Problem: When I clicked on submit I didn't see any update. Second trial gave the expected result. When I refreshed the page the lost record (first hit was successful) was on spot.
Model
[Serializable]
public abstract class AbstractEntity {
public Guid Id { get; set; }
public DateTime LastModified { get; set; }
}
[Serializable]
public class Product : AbstractEntity {
public Product() {
this.Attachments = new HashSet<Attachment>();
}
public String Title { get; set; }
public String Commentary { get; set; }
public DateTime PlacedOn { get; set; }
public String User { get; set; }
public ICollection<Attachment> Attachments { get; set; }
}
[Serializable]
public class Attachment {
public String MimeType { get; set; }
public String Description { get; set; }
public String Filename { get; set; }
}
Controller
[HandleError]
public class ProductController : Controller {
private readonly IDocumentSession documentSession;
public ProductController(IDocumentSession documentSession) {
this.documentSession = documentSession;
}
public ActionResult ListRecent() {
return View(ListAll());
}
[Audit, HttpPost]
public ActionResult Delete(Guid id) {
documentSession.Delete<Product>(documentSession.Load<Product>(id));
documentSession.SaveChanges();
return PartialView("ProductsList", ListAll());
}
[Audit, HttpPost]
public ActionResult Create(Product product) {
if(ModelState.IsValid) {
documentSession.Store(product);
documentSession.SaveChanges();
}
return PartialView("ProductsList", ListAll());
}
private IEnumerable<Product> ListAll() {
return documentSession.Query<Product>().ToArray();
}
}
Views ('scriptless')
Layout
<head>
<title>#ViewBag.Title</title>
<link href="#Url.Content("~/Content/stylesheets/normalize.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/stylesheets/site.core.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-1.7.2.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
</head>
<body>
<div id="main-wrapper">
<div id="header">[#Html.ActionLink("List", "ListRecent", "Product")]</div>
<div id="content">#RenderBody()</div>
</div>
</body>
ListRecent.cshtml
#model IEnumerable<lamp.DomainLayer.Entities.Product>
#{
ViewBag.Title = "ListRecent";
var options = new AjaxOptions {
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "productsList"
};
}
<h2>List</h2>
#Html.Partial("ProductsList", Model)
#using(Ajax.BeginForm("Create", "Product", options)) {
<fieldset>
<p>
<label class="autoWidth">Title</label>
#Html.Editor("Title")
#Html.ValidationMessage("Title")
</p>
<p>
<label class="autoWidth">Commentary</label>
#Html.TextArea("Commentary")
#Html.ValidationMessage("Commentary")
</p>
#* Some fields I have omitted.. *#
<input type="submit" value="submit" />
<input type="reset" value="clear" />
</fieldset>
}
ProductsList.cshtml
#model IEnumerable<lamp.DomainLayer.Entities.Product>
#{
var options = new AjaxOptions {
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "productsList"
};
}
<div id="productsList">
#foreach(var p in Model) {
<div class="productCard">
<p class="title"><strong>Title</strong>: #p.Title</p>
<p class="author"><strong>User</strong>: #p.User</p>
<p class="date"><strong>Placed on</strong>: #idea.PlacedOn.ToShortDateString()</p>
<p class="link">#Html.ActionLink("details", "Details", "Product")</p>
<p class="link">
#using(Ajax.BeginForm("Delete", "Product", new { id = p.Id }, options)) {
<input type="submit" value="you!" />
}
</p>
</div>
}
</div>
I guess it is IE's fault (precisely the way,how IE cache AJAX requests). Look here-it could be solution:
http://viralpatel.net/blogs/ajax-cache-problem-in-ie/
Ok. Darin was right! I found out that changing my controller code to this one:
private IEnumerable<Product> ListAll() {
return documentSession
.Query<Product>()
.Customize((x => x.WaitForNonStaleResults()))
.ToArray();
}
fixes everything.
.Customize((x => x.WaitForNonStaleResults()))
is the solution!
Thanks everyone!
My page which for online shoping, contains two parts. First part is a list of products.
#model WebUI.Models.CakesListViewModel
#foreach (var p in Model.Cakes) {
Html.RenderPartial("CakesList", p);
}
Each product appears as partial view. CakesList.cshtml
#model Domain.Entities.Cake
<div>
#if (Model.ImageData != null) {
<div style="float:left;margin-right:20px">
<img width="75" height="75" src="#Url.Action("GetImage", "Cake", new { Model.Id })" />
</div>
}
<b>#Model.Name<br />
#Model.Price</b><br />
#Model.Description
#using (Html.BeginForm("AddToCart", "Cart"))
{
#Html.HiddenFor(x => x.Id)
#Html.TextBox("quantity", "", new { style = "width: 20px; text-align: center" })
<input type="image" src="../Images/basket.jpg" />
}
</div>
All page is reloading, after clicking basket image button, but I need to reload only second part of page. How can I do it.
Second part is sum of ordered products.
#model Domain.Entities.Cart
#{
Layout = null;
string str = String.Format("{0}", Model.ComputeTotalValue());
}
<div id="cart">
#Html.ActionLink(str, "Index", "Cart")
</div>
Which is appeared from _Layout.cshtml
</head>
<body>
<div id="header">
#{Html.RenderAction("Summary", "Cart");}
<div class="title">Cakes</div>
</div>
<div id="categories">
#{ Html.RenderAction("Menu", "MenuItems"); }
</div>
<div id="content">
#RenderBody()
</div>
</body>
</html>
//CakeController
namespace WebUI.Controllers
{
public class CakeController : Controller
{
public int PageSize = 4;
private ICakeRepository repository;
public CakeController(ICakeRepository cakeRepository)
{
repository = cakeRepository;
}
public FileContentResult GetImage(int id)
{
Cake prod = repository.Cakes.FirstOrDefault(p => p.Id == id);
if (prod != null)
return File(prod.ImageData, prod.ImageMimeType);
else
return null;
}
public ActionResult OnlineShop(string regions, int page = 1)
{
CakesListViewModel viewModel = new CakesListViewModel
{
Cakes = repository.Cakes
.Where(p => regions == null || p.Name.Trim() == regions),
PagingInfo = new PagingInfo
{
CurrentPage = page,
ItemsPerPage = PageSize,
TotalItems = 1
},
CurrentCategory = "category"
};
return View("OnlineShop", viewModel);
}
}
}
//OnlineShop.cshtml
#model WebUI.Models.CakesListViewModel
#{
ViewBag.Title = "Cakes";
}
#foreach (var p in Model.Cakes) {
Html.RenderPartial("CakesList", p);
}
//CakesList.cshtml
#model Domain.Entities.Cake
#if (Model.ImageData != null) {
<div style="float:left;margin-right:20px">
<img width="75" height="75" src="#Url.Action("GetImage", "Cake", new { Model.Id })" />
</div>
}
<b>#Model.Name<br />
#Model.Price</b><br />
#Model.Description
#using (Ajax.BeginForm("AddToCart", "Cart", new AjaxOptions { HttpMethod = "Get", InsertionMode = InsertionMode.Replace, UpdateTargetId = "mydiv" }))
{
#Html.HiddenFor(x => x.Id)
#Html.TextBox("quantity", "", new { style = "width: 20px; text-align: center" })
<input type="image" src="../Images/basket.jpg" />
}
//CartController
namespace WebUI.Controllers
{
public class CartController : Controller
{
private ICakeRepository repository;
private IOrderProcessor orderProcessor;
public CartController(ICakeRepository repo, IOrderProcessor proc)
{
repository = repo;
orderProcessor = proc;
}
public ActionResult AddToCart(Cart cart, int id, int quantity = 1)
{
Cake cake = repository.Cakes.FirstOrDefault(p => p.Id == id);
if (cake != null)
cart.AddItem(cake, quantity);
return RedirectToAction("OnlineShop", "Cake");
}
public ActionResult RemoveFromCart(Cart cart, int id)
{
Cake cake = repository.Cakes.FirstOrDefault(p => p.Id == id);
if (cake != null)
cart.RemoveLine(cake);
return RedirectToAction("Index", "Cart");
}
public ViewResult Index(Cart cart, string returnUrl)
{
return View(new CartIndexViewModel
{
Cart = cart,
ReturnUrl = returnUrl
});
}
public ViewResult Summary(Cart cart)
{
return View(cart);
}
}
}
//Summary.cshtml
#model Domain.Entities.Cart
#{
Layout = null;
string str = String.Format("{0}", Model.ComputeTotalValue());
}
<div id="cart">
<p>
<img src="../Images/basket.jpg" />
<div id="mydiv">#Html.ActionLink(str, "Index")</div>
</p>
</div>
<h2>About</h2>
<p>
Put content here.
</p>
#Ajax.ActionLink("Link Text", "ActionThatWillReturnContent", new AjaxOptions
{
HttpMethod = "GET",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "ContainerThatIWillUpdate"
})
<div id="ContainerThatIWillUpdate"></div>
This will call "ActionThatWillReturnContent" and insert content inside of "ContainerThatIWillUpdate".
Alternative is to use jQuery.ajax which is a lot nicer, but will require a little reading/playing around with.
Update 1:
You send an AJAX request to your action method called AddToCart. This method does some processing and then returns a full view:
return RedirectToAction("OnlineShop", "Cake");
What you want to do, is return a partial view, that will be placed inside of "mydiv", which is your update target id.
Your action method needs to be modified to return PartialView, rather than ActionResult:
public PartialViewResult AddToCart(Cart cart, int id, int quantity = 1)
{
// Inside this action method, you don't want to return a redirect to action,
// you want to return partial view
return PartialView(); // This has three constructors, so you'll need to do a bit of digging.
}
I'm having a problem getting a form to work without javascript being enabled.
This should be enough to go on, ask if you need to know anything else - I don't want to just put the whole solution up here!
~/Views/_ViewStart.cshtml:
#{ Layout = "~/Views/Shared/Layout.cshtml"; }
~/Views/Shared/Layout.cshtml:
#using System.Globalization; #{ CultureInfo culture = CultureInfo.GetCultureInfo(UICulture); }<!DOCTYPE html>
<html lang="#culture.Name" dir="#(culture.TextInfo.IsRightToLeft ? "rtl" : "ltr")">
<head>
<title>AppName :: #ViewBag.Title</title>
<link href="#Url.Content("~/favicon.ico")" rel="shortcut icon" type="image/x-icon" />
<link href="#Url.Content("~/apple-touch-icon.png")" rel="apple-touch-icon" />
<link href="#Url.Content("~/Content/css/site.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Content/js/jquery-1.6.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Content/js/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Content/js/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Content/js/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Content/js/app.js")" type="text/javascript"></script>
#RenderSection("SectionHead", false)
</head>
<body>
<div id="page-container">
<div id="nav">
<div id="nav-user">
#{ Html.RenderAction("LoginStatus", "Account"); }
#{ Html.RenderPartial("CultureSelector"); }
</div>
</div>
<div id="page-content">
<h2>#ViewBag.Title</h2>
#RenderBody()
</div>
</div>
</body>
</html>
~/Views/Account/Index.cshtml:
#model AccountFilterModel
#{
ViewBag.Title = "Account Home";
var loadingId = "loading" + new Random().Next();
Model.FilterFormId = "filter-account-form";
}
#using (Ajax.BeginForm("List", "Account", Model, new AjaxOptions { UpdateTargetId = "result-list", LoadingElementId = loadingId }, new { id = "filter-account-form" })) {
<!-- form controls and validation summary stuff -->
<input id="filter" type="submit" value="Filter" />
<span id="#loadingId" style="display: none">
<img src="#Url.Content("~/Content/images/ajax-loader.gif")" alt="Loading..." />
</span>
}
<div id="result-list">
#{ Html.RenderAction("List", Model); }
</div>
~/Views/Account/List.cshtml:
#model FilterResultModel
#helper SortLink(AccountSort sort, SortDirection dir) {
string display = (dir == SortDirection.Ascending ? "a" : "d"); // TODO: css here
if (Model.Filter.SortBy != null && ((AccountSortModel)Model.Filter.SortBy).Sort == sort && dir == Model.Filter.SortOrder) {
#:#display
} else {
FilterModel fm = new FilterModel(Model.Filter);
fm.SortBy = AccountSortModel.SortOption[sort];
fm.SortOrder = dir;
#display
}
}
#if (Model.Results.Count > 0) {
var first = Model.Results.First();
<table>
<caption>
#string.Format(LocalText.FilterStats, Model.FirstResultIndex + 1, Model.LastResultIndex + 1, Model.CurrentPageIndex + 1, Model.LastPageIndex + 1, Model.FilteredCount, Model.TotalCount)
</caption>
<thead>
<tr>
<th>
#Html.LabelFor(m => first.Username)
<span class="sort-ascending">
#SortLink(AccountSort.UsernameLower, SortDirection.Ascending)
</span>
<span class="sort-descending">
#SortLink(AccountSort.UsernameLower, SortDirection.Descending)
</span>
</th>
<!-- other table headers -->
</tr>
</thead>
<tbody>
#foreach (AccountModel account in Model.Results) {
<tr>
<td>#Html.EncodedReplace(account.Username, Model.Filter.Search, "<span class=\"filter-match\">{0}</span>")</td>
<!-- other columns -->
</tr>
}
</tbody>
</table>
Html.RenderPartial("ListPager", Model);
} else {
<p>No Results</p>
}
Relevant part of AccountController.cs:
public ActionResult Index(AccountSort? accountSort, FilterModel model = null) {
FilterModel fm = model ?? new FilterModel();
if (accountSort.HasValue) fm.SortBy = AccountSortModel.SortOption[accountSort.Value];
return View(fm);
}
public ActionResult List(AccountSort? accountSort, FilterModel model = null) {
FilterModel fm = model ?? new FilterModel();
if (accountSort.HasValue) fm.SortBy = AccountSortModel.SortOption[accountSort.Value];
return Request.IsAjaxRequest() ? (ActionResult)PartialView("List", Service.Get(fm)) : View("Index", model);
}
With javascript enabled, this works fine - the content of div#result-list is updated as expected.
If I don't do the Request.AjaxRequest() and just return the PartialView, then with javascript disabled I get a page with just the content of the results on it. If I have the code as above, then I get a StackOverflowException.
How do I get this to work?
Solution
Thanks to #xixonia, I discovered the problem - here is my solution:
public ActionResult List(AccountSort? accountSort, FilterModel model = null) {
FilterModel fm = model ?? new FilterModel();
if (accountSort.HasValue)
fm.SortBy = AccountSortModel.SortOption[accountSort.Value];
if (Request.HttpMethod == "GET")
return PartialView("List", Service.Get(fm));
if (Request.HttpMethod == "POST")
return Request.IsAjaxRequest() ? (ActionResult) PartialView("List", Service.Get(fm)) : RedirectToAction("Index", model);
return new HttpStatusCodeResult((int) HttpStatusCode.MethodNotAllowed);
}
You can use the following extension method to determine if the request is an ajax request
Request.IsAjaxRequest()
If it is, you can return a partial view, otherwise you can return a full view or redirect.
if(Request.IsAjaxRequest())
{
return PartialView("view", model);
}
else
{
return View(model);
}
edit: here's the problem:
The "List" is returning the "Index" view when the request is not an AJAX request:
public ActionResult List(AccountSort? accountSort, FilterModel model = null) {
FilterModel fm = model ?? new FilterModel();
if (accountSort.HasValue) fm.SortBy = AccountSortModel.SortOption[accountSort.Value];
return Request.IsAjaxRequest() ? (ActionResult)PartialView("List", Service.Get(fm)) : View("Index", model);
}
The "Index" view is rendering the "List" action:
#{ Html.RenderAction("List", Model); }
AKA: Recursion.
You need to engineer a way to display your list without drawing the index page, or make your index page draw a partial view with your list modal as a parameter.