Script works on Create, but in Edit doens't - c#

guys.
I have a View on my ASP.NET MVC Project.
This View has a lot of fields and a script to search some data.
<link href="#Url.Content("~/Content/styles/people.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/people.js")" type="text/javascript"></script>
<input type="hidden" id="selectiveAccess" name="selectiveAccess" value="#ViewBag.SelectiveAccess" />
<input type="hidden" id="peopleID" name="peopleID" value="#ViewBag.PeopleID" />
<div id="content">
<h1>People - Create</h1>
<h3>All the fields with (*) are required.</h3>
#using (Html.BeginForm("Save", "People", FormMethod.Post))
{
#Html.Partial("EnabledCourses")
#Html.Partial("GeneralData")
#Html.Partial("AddressData")
#Html.Partial("ContactData")
#Html.Partial("OtherInformations")
#Html.Partial("Research")
Back to the top
<div id="divErrors"></div>
<div id="actions">
<ul style="list-style: none;">
<li style="display: inline"><input type="reset" id="clear" style="height: 3em; width: 10em" value="Clear form" /></li>
<li style="display: inline"><input type="submit" id="continue" style="height: 3em; width: 10em" value="Continue" /></li>
</ul>
</div>
}
When I call Index(), the script works fine.
public ActionResult Index()
{
ViewBag.PeopleID = string.Empty;
return View();
}
When I call Edit(), the same script doensn't works.
public ActionResult Edit(long peopleID)
{
ViewBag.PeopleID = peopleID;
return View("Index");
}
This is the script:
function searchCityByPostalCode() {
var postalCode = {
'postalCode': $('#postalCode').val()
};
$.get(
'people/SearchCityByPostalCode',
postalCode,
function (city) {
// do something that works.
}
);
}
Anyone knows the problem?
Thanks!!!

Most likely is is due to the relative link you are using.
Index allows you to do something like this
www.mysite.com/Mycontroller/ - Goes to Index
www.mysite.com/Mycontroller/Index - Goes to Index (same as above)
However edit would force you to use the second form since there is no default route value
www.mysite.com/Mycontroller/Edit/{id}
Meaning that when you call the function for get in the index the request looks like
www.mysite.com/Mycontroller/people/SearchCityByPostalCode
And edit looks like this which is a diffrent path
www.mysite.com/Mycontroller/Edit/people/SearchCityByPostalCode
So basically you need to use an absolute reference so that the URL will work from the root of the site.
$.get(
'/people/SearchCityByPostalCode',
postalCode,
function (city) {
// do something that works.
}
);

Related

How to retain search results when clicking browser's back button - ASP.NET Core MVC

I am creating an ASP.NET Core 3 MVC application that has a Customers tab in addition to the Home tab. On the Customers tab there is an input box where the user adds a search criterion (number of days) and a Search button. When the button is clicked then a list of Customer Ids is shown underneath (using jQuery and a Partial View). When the user clicks on a customer Id then the customer information is shown in a different page. However when I click on the browser's back button or on the 'Customers' tab then the criterion added and the search results disappear.
I have tried using the ResponseCache attribute to retain the search results but I could not make it work. I have also tried using the Cache Tag Helper but again was not successful. Anyone can help?
CustomersController
public class CustomersController : Controller
{
private readonly DbContext _context;
public CustomersController(DbContext context)
{
_context= context;
}
public IActionResult Index()
{
return View();
}
public IActionResult DisplayCustomerIdList(string searchText)
{
List<CustomerDetailViewModel> customers = _context.GetAll().ToList();
CustomerIndexViewModel model = new CustomerIndexViewModel()
{
Customers = customers
};
return PartialView("_CustomerIdListView", model);
}
public IActionResult Detail(decimal? Id)
{
Customer customer = _context.GetCustomerById(Id);
CustomerDetailViewModel model = new CustomerDetailViewModel(customer);
return View(model);
}
}
Index.cshtml
#{
ViewData["Title"] = "Customers Page";
}
#section Scripts {
<script type="text/javascript" src="~/lib/jquery/dist/jquery.min.js"></script>
<script>
var url = '#Url.Action("DisplayCustomerIdList", "Customers")';
$('#search').click(function () {
var keyWord = $('#NumberOfDays').val();
$('#searchResults').load(url, { searchText: keyWord });
return false;
})
</script>
}
<body>
<div class="input-group mb-3 w-50">
<input type="text" class="form-control mr-2" placeholder="Number of days" autocomplete="off" id="NumberOfDays">
<button id="search" class="btn btn-outline-info mb-2">Search</button>
</div>
<div id="searchResults"></div>
</body>
_CustomerIdListView.cshtml
#model MyProject.Models.CustomerIndexViewModel
<div class="card border-info mb-3 shadow" style="width:220px; height: 625px; overflow-y: scroll;">
<div class="card-header">Customer Ids</div>
<div class="list-group">
#foreach (CustomerDetailViewModel customerdetails in Model.Customers)
{
<a asp-controller="Customers" asp-action="Detail" asp-route-id="#customerdetails.CustomerId" class="list-group-item list-group-item-action">
#customerdetails.CustomerId
</a>
}
</div>
</div>
Detail.cshtml
#model MyProject.Models.CustomerDetailViewModel
<h3>Customer Information</h3>
<ul>
<li>#Model.CustomerId</li>
<li>#Model.FullName</li>
</ul>
Do the search via a GET request (rather than post). That way, the actual URL the user is sent to includes the query.
<form action="/foo" method="get">
I have figured out why this was not working and thought to add it here in case someone else has the same issue.
It turns out that the jQuery .load() method creates a POST request when the input parameter is an object (and a GET request when it is a String). So, because the ResponseCache attribute does not work with POST requests, the caching was not working.

Webmatrix how to add a class if input type text box is not empty?

I want to add a class if input type text box is not empty or null. I'm trying to do something like this.
.cshtml
#{
var value= string.IsNullOrEmpty;
}
<form action="">
<input type="text" value="#value" class="#(value=!null ? "thisclass" : "")">
</form>
I'm sorry for this bad example but I really don't know how to explain it and I'm not using MVC or Database, this is a simple Input type="text" box. Please Help!
Started a new MVC-project.
This is the code I use in Index.cshtml and it works fine. (I get a red background in the text field)
#{
ViewBag.Title = "Home Page";
var value = string.Empty;
}
<style type="text/css">
.testclass {
background-color: red;
}
</style>
<div class="jumbotron">
<h1>ASP.NET</h1>
<input type="text" class="#(string.IsNullOrWhiteSpace(value) ? "testclass" : "")" />
<p class="lead">ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.</p>
<p>Learn more »</p>
</div>
As stated by NoLifeKing, this is the server side solution to test if the input is empty and change its class accordingly:
<input type="text" id="testinput" value="#value"
class="#(string.IsNullOrEmpty(value) ? "thisclass" : "")" />
If you want that the input class changes as you write, you must use jquery, something like:
$(document).ready(function () {
$('#testinput').keyup(function () {
if (!this.value) {
$(this).addClass('thisclass');
} else {
$(this).removeClass('thisclass');
}
});
});

Showing message in a razor view based on a result from execution of controller method

I'm working on asp.net mvc 3 application. I'm implementing a razor view which have tow main functions - to build/display form based on a data from a data base and to show images related to this form in a custom (made by me) image gallery that allows upload and delete of image.
So generally this is my view with both forms for visualizing the form and showing and uploading image(s) :
#model List<DataAccess.MCS_DocumentFields>
#{
ViewBag.Title = "Документ";
}
<div id="alabala">
<div id="drawForm">
#using (Html.BeginForm("UpdateDocument", "Forms", FormMethod.Post))
{
<table border="1" id="drawDocument">
<colgroup>
<col span="1" style="width: 10%;" />
<col span="1" style="width: 40%;" />
<col span="1" style="width: 25%;" />
<col span="1" style="width: 25%;" />
</colgroup>
#Html.Partial("_PartialHeader", Model)
#Html.Partial("_PartialDrawing", Model)
#Html.Partial("_PartialBody", Model)
#Html.Partial("_PartialFooter", Model)
</table>
if (ViewBag.Status == 1)
{
<button type="submit" id="submitDocument">Запази</button>
<button style="float:right;" id="finalizeDocument">Приключи</button>
}
else
{
#Html.ActionLink("Назад", "Index")
}
}
</div>
<div id="imageContainer">
<div id="imageGallery" style="overflow: scroll">
<img src="file:\\..." alt="docImg" style="width: 190px; height: auto"/>
#Ajax.ActionLink("Delete", "DeletePicture", new { documentID = Model[0].Id },
new AjaxOptions
{
Confirm = "Are you sure?",
OnComplete = "$('#blah').attr('src', '#').attr('style', 'display:none;'); $('#Image1').attr('src', '#').attr('style', 'display:none;'); $('#DelPic').attr('style', 'display:none;');"
})
<img src="file:\\..." alt="docImg" style="width: 190px; height: auto"/>
#Ajax.ActionLink("Delete", "DeletePicture", new { documentID = Model[0].Id },
new AjaxOptions
{
Confirm = "Are you sure?",
OnComplete = "$('#blah').attr('src', '#').attr('style', 'display:none;'); $('#Image1').attr('src', '#').attr('style', 'display:none;'); $('#DelPic').attr('style', 'display:none;');"
})
</div>
#using (Html.BeginForm("Upload", "Forms", FormMethod.Post))
{
<input name=#Model[0].DocumentId type="hidden" />
<input type="file" name="datafile" id="file" onchange="readURL(this);" />
<input type="button" name="Button" value="Upload" id="UploadButton" onclick="fileUpload(this.form,'/forms/upload','upload'); return false;"/>
<div id="upload" style="display: inline-block;">
<img id="blah" src="#" alt="your image" style="display:none;"/>
</div>
}
</div>
</div>
The first form is where I show the data for a current form/document and because they are editable I have submit button. I need the second form to submit the selected picture to my controller and there to perform the business logic.
So once a picture is selected and Upload button is clicked I get to my controller :
public ActionResult Upload(FormCollection collection)
{
WebImage UploadImage = WebImage.GetImageFromRequest();
long documentID;
string finalImageName = null;
if (!long.TryParse(collection.AllKeys[0], out documentID))
//More code...
Where I have the image and the id of the document that it belongs to and what I need is to perform some checks/validations and finally to coy the selected image to dedicated directory and save the name to the data base.
The problem is that I have all the logic written except the one that will show the correct messages for the different outputs like :
if (imagePath.Length > 247)
{
//TODO message that the path is too long
//TODO this return View() is temp, replace with something suitable
return View();
}
//...
System.IO.File.Copy(UploadImage.FileName, imagePath);
}
catch (Exception ex)
{
//TODO copy failed return message
return View();
}
//...
These are all different outputs from the execution of the same method and in the main view I want to show a proper message for each one of them. What I'm not sure is if I still have an option to save my work and still implement the message logic? Thinking now it seems that if I was using Ajax in some form it would be a lot easier now but I'm not. The only think I can think of know is creating ViewBag property, and returning it with the model to the view where to check the different properties and show some message if necessary based on that, but this means a lot of additional logic in my view, resending data from the database that I already have shown in my view and a lot of double work said in short, something that I consider as a bad programming, but maybe I got myself into this. So what is the best course of action from here on. Is it best to just remove my code and search for a way to do this with AJAX?
You can't upload a file using AJAX - you'd need some sort of 3rd party workaround. You need to return the original view from the Upload() method, with the appropriate model, and also a flag within the ViewBag somewhere to display the message, e.g.
public ActionResult Upload(UpdateDocumentModel model) {
...
if (imagePath.Length > 247) {
model.ErrorMessage = Errors.Over247;
return View("UpdateDocument", model);
}
...
return RedirectToAction("UploadOk");
}
I've changed your FormCollection to a strongly-typed model for ease of reading, plus that's what MVC.net is there for. The Errors.Over247 could be a string resource somewhere in your project, or a boolean flag which the View then reads to show a certain piece of HTML.
just use TempData instead of ViewBag
TempData["ErorrMessegge"] = "SomeMessage to view";
#TempData["ErorrMessegge"]
You can simply use TempData[] in order to pass parameter from Controller to View like below:
Controller:
[HttpPost]
public ActionResult Add(Applicant applicant)
{
repository.SaveApplicant(applicant);
TempData["message"] = "The applicant has been saved succesfully.";
return View(applicant);
}
View:
#if (TempData["message"] != null)
{
<div>#TempData["message"]</div>
}

why AjaxForm is not working for me?

I have the following form, what i want to do is, when people click on the Search button,
an request will file to server, and server will return a new set of result, and i will re-render the div to present the new result
#using (Ajax.BeginForm("Search", new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "DivToUpdate" }))
{
<div style="margin: 10px 50px 5px 50px;">
#Html.TextBox("instrument", (string)ViewBag.DefaultInstrumentStr)
<input type="submit" value="Search" />
</div>
}
<div id="DivToUpdate" style="width: 100%; display: none;">
#if (Model != null)
{
#Html.Partial("_InstrumentList", #Model);
}
else
{
<span>Loading ....</span>
}
</div>
Here is my controller implementation:
public ActionResult Search(string instrument)
{
// ... base on the input perform certain action to generate a list of result
return PartialView("_InstrumentList", instruments);
}
when i run it, after clicking the search, i will only see the partial view in the browser, the data does not update the div.
anyone has any idea what did i do wrong?
Thanks.
anyone has any idea what did i do wrong?
You forgot to reference the jquery.unobtrusive-ajax.js script to your page:
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
You must reference some script:
in MVC3(set UnobtrusiveJavaScriptEnabled true):
jquery.unobtrusive-ajax.js
in MVC2 and MVC3(set UnobtrusiveJavaScriptEnabled false):
MicrosoftMvcAjax.js
For the differents,you can look at this:Unobtrusive Client Validation in ASP.NET MVC 3
The div which you are trying to update, must be inside Ajax.BeginForm brackets.

UL toggle working in FF and not in IE 7

I have an list that toggles with no problem in FF. I need this working IE for it to be production ready.
It seems (IE) to apply the js to the first #orderItem and the first #familiy only. The rest of the items in the list are ignored.
Any help would be great.
A piece of the HTML (large list):
<div class="classificationContainer">
<ul class="classification" id="orderUL">
<li id="orderItem" class="ordrheading">
<div class="order">
<a href="?nav=search_recherche&lang=en">
<img src="http://dev.ncr.ec.gc.ca/publications/bba-aob/images/node_closedc.gif" alt="By Classification" id="OrdListImage" />
Apodiformes (Swifts and Hummingbirds)
</a>
</div>
<ul class="classification" id="FamilyList">
<li id="familiy">
<div class="family">
<a href="?nav=search_recherche&lang=en">
<img src="http://dev.ncr.ec.gc.ca/publications/bba-aob/images/node_closedc.gif" alt="Family" id="FamListImage" />
Apodidae (Swifts)
</a>
</div>
<ul class="classification" id="SpiecesList">
<li>
<img src="http://dev.ncr.ec.gc.ca/publications/bba-aob/images/node_leafc.gif" alt="Species" />
Chimney Swift (Chaetura pelagica)
</li>
</ul>
</li>
<li id="familiy">
<div class="family">
<a href="?nav=search_recherche&lang=en">
<img src="http://dev.ncr.ec.gc.ca/publications/bba-aob/images/node_closedc.gif" alt="Family" id="FamListImage" />
Trochilidae (Hummingbirds)
</a>
</div>
<ul class="classification" id="SpiecesList">
<li>
<img src="http://dev.ncr.ec.gc.ca/publications/bba-aob/images/node_leafc.gif" alt="Species" />
Ruby throated Hummingbird (Archilochus colubris)
</li>
<li>
<img src="http://dev.ncr.ec.gc.ca/publications/bba-aob/images/node_leafc.gif" alt="Species" />
Rufous Hummingbird (Selasphorus rufus)
</li>
</ul>
</li>
</ul>
</li></ul></div>
I have the following jquery functions:
<script type="text/javascript">
$(document).ready(function () {
// toggle action for the order to familiy
$("li#orderItem").click(function (event) {
// toggle the image
var src = ($("#OrdListImage", this).attr("src") == "/images/node_closedc.gif")
? "/images/node_openc.gif"
: "/images/node_closedc.gif";
$("img#OrdListImage", this).attr("src", src);
//toggle the ul
$('ul#FamilyList', this).toggle($('ul#FamilyList', this).css('display') == 'none');
// stop all link actions
return false;
});
//toggle action from familiy to speices
$("li#familiy").click(function () {
// toggle the image
var src = ($("#FamListImage", this).attr("src") == "/images/node_closedc.gif")
? "/images/node_openc.gif"
: "/images/node_closedc.gif";
$("img#FamListImage", this).attr("src", src);
//toggle the ul
$('ul#SpiecesList', this).toggle($('ul#SpiecesList', this).css('display') == 'none');
// stop all link actions
return false;
});
});
Also check if id's are not repeated (there is only one #orderItem, only one #familiy and etc.). "id" attribute must be unique in html document, "class" can be repeated.
The toggle function provided by jQuery is not guaranteed to work. I lost the reference where I read this (was on jQuery's homepage). I encountered the same problem and (as suggested by jQuery) implemented my own toggle function. I'd suggest trying this, as it's not much work and could provide you a solution.

Categories

Resources