So I am very new ASP.NET MVC, I took an intro ASP.NET months and months ago, and have unfortunately forgotten nearly everything :(
I have been given a task to add a lookup button to a page that takes in a username from a textbox and verifies whether or not that username is valid.
I have spent hours and hours trying to get it to work. Unfortunately what i realllyyy need to do is sit down for a few weeks and re-teach myself and learn javascript, jquery, asp.net mvc. I am going to learn it all, but this assignment is to small and specific to spend weeks learning languages and frameworks just to begin solving.
Here is where i'm at:
Structure of Controller:
public class NewUserRequestController : Controller
{
// GET: NewUserRequest
public ActionResult Index()
{
return View(new NewUserRequest());
}
[HttpPost]
[ValidateAntiForgeryToken()]
public ActionResult LookupLDN(ITFormsLibrary.NewUserRequest req)
{
//Code that Verifies user etc
return View(req);
}
[HttpPost]
[ValidateAntiForgeryToken()]
public ActionResult Submit(ITFormsLibrary.NewUserRequest req)
{
//Code that handles submission validation & errorvalidation
return View("Index", req);
}
}
Now in the view, I have tried messing around with:
#using((Ajax.BeginForm("LookupLDN", "NewUserRequest", FormMethod.Post, new AjaxOptions { UpdateTargetId = "NewUserIfo"}, new { #class = "form-inline", role = "form" }))
Only to discover I can't nest forms.
I have tried:
#Ajax.ActionLink("Lookup", "LookupLDN", "NewUserRequest", new { Model},null, new { #class = "form-inline", role = "form" })
and
#HTML.ActionLink("Lookup", "LookupLDN", "NewUserRequest", new { Model})
both of which return 404 for some reason.
I have also tried:
<input type="button" value="Lookup" onclick="return lookupLDN()"/>
But, I don't know how to construct a javascript statement to handle an asynchronous POST? - Should I even be trying to POST?
If any of you understand what I am trying to accomplish and can provide help, I would be extremely grateful. thank you!
How about JSON.
EDITED as per Tommy's comment. Use POST instead of GET.
It should be a POST method because you are sending data to the server
and asking it to take action on that data (POST) and not just asking
the server to give us information without sending it anything (GET).
With POST, you can add checks around CSRF tokens, don't have to worry
about the Googlebot doing something it shouldn't, etc.
HTML (VIEW)
<input type="button" id="btnLookupUser" value="Lookup" />
JAVASCRIPT
$(document).ready(function () {
$('#btnLookupUser').click(function () {
var vUsername= $('#txtUserName').val();
if (vUsername.trim() == '') {
return;
}
else
{
//URL to your JSON method. (here I suppose you have a LookupUser action method. Change application path the way it works for you.)
$.ajax({
url: applicationPath + '/LookupUser',
type: 'POST',
dataType: 'json',
data: { userName: encodeURIComponent(vUsername.trim()),
cache: false,
success: function (result) {
//Do your logic based on the result.
switch (result) {
case true:
break;
default:
break;
}
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
alert(thrownError);
})
});
});
CONTROLLER
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult LookupUser(string userName)
{
//Your logic
return Json("Whether is valid or not"); //You can as well deny GET here.
}
Related
I have a special case where I need to have a grid with an "Add New Record" row, that exists within an MVC form.
Since I can't submit the new record details, without submitting the entire form, I decided to make the record submit button call a Javascript method that should POST the data to a method on my controller. In short, here is an example of what I'm doing. The code below is copy-and-pasted from my project, with only minor modifications for brevity.
...
<table>
CODE HERE FOR MY GRID...
</table>
...
<input class="data_field" id="MainSession_Name" type="text" />
<input class="data_field" id="MainSession_Type" type="text" />
<button id="btnAddMainSession" class="button" onclick="SubmitMainSession()" type="button">Add Session</button>
...
<script>
var SubmitMainSession = function()
{
var data = {
Name: $('MainSession_Name').val(),
RecType: $('MainSession_Type').val(),
};
$.post(
{
url: "/Session/Add",
data: data,
callback: function(res, status)
{
if (res !== "OK")
alert("There was a problem processing the request. " + res);
else
location.reload(true);
}
});
}
</script>
My intent is simple. After the user enters new details for a session, they will click on the Add Session button. JQuery will make a POST request passing my data to my page controller.
Here is an abbreviated variation of my controller:
//Index that initially loads the data.
public ActionResult Index(int id = -1)
{
SessionModel sm = new SessionModel(id);
sm.CanEdit = true;
return View(sm);
}
//The containing model manages a HUGE form,
//across multiple BootStrap.js tabs. We save
//all other, non-sub-record related deets here.
public ActionResult Submit(SessionModel model)
{
model.Save();
return Redirect(Url.Content("~/"));
}
//Since there are multiple grids, I need to
//have a way to add new Session records.
//This is my first attempt at trying to
//create a POST method on my controller.
[HttpPost]
public string Add(AddSessionObject data)
{
//If I can ever get here, I'll save the data.
return "OK";
}
public class AddSessionObject
{
public string Name;
public string RecType;
}
What I'm experiencing is that when I make the $.post(...) call in JQuery, MVC always calls the Index(...) method, rather than the Add(...) method. What am I doing wrong?
try using this syntax:
var data = {
Name: $('MainSession_Name').val(),
RecType: $('MainSession_Type').val(),
};
$.post("/Session/Add", data, function(res, status) {
if (res !== "OK")
alert("There was a problem processing the request. " + res);
else
location.reload(true);
});
https://api.jquery.com/jquery.post/
So i've been searching stack for hours and cannot seem to find a solution. I'm trying to implement a basic jquery autocomplete, but when i click/select the item in the autocomplete dropdown to send me to a new page, my httppost actionresult isn't returning the view. It runs through the httppost controller fine (all paramaters are passed,queries run, models are passed to views, etc). I'm pretty sure it's due to the window.location.reload(); in my ajax post, but can't seem to figure this one out. I also tried window.location.href = link; but that wasn't working either. Please help :(
JS
$("#queryTypeInput").autocomplete({
source: "/Dashboard/EnterMatterFormAjax/",
select: function (event, ui) {
var inputVal = ui.item.value.substring(0, 10);
$.ajax({type:"POST",
url:"Dashboard",
data:{ queryType: queryTypeval },
success: function (result) {
window.location.reload(); //this is where i think the issue is
}
})
});
EnterMatterFormAjax Controller (WORKING FINE)
public JsonResult EnterMatterFormAjax(string term)
{
var termReq = Request["term"];
var termReq2 = "";
if (termReq.All(char.IsDigit))
{
termReq2 = termReq + "%";
}
else
{
termReq2 = "%" + termReq + "%";
}
var ajaxMatterData = GetAjaxMatterData(termReq2);
return Json(ajaxMatterData, JsonRequestBehavior.AllowGet);
}
Index Controller (WORKING FINE)
[HttpPost]
public ActionResult Index(string queryType)
{
...goes through code logic...
return View();
}
I just resubmitted my form after the autocomplete select instead of using the window.location.href as #KarthikMR mentioned. I would have had to change around my controller actions, so i just took the simplest road. #KarthikMR suggestion did work though when i changed my actions, so this is a viable option! updated js below:
$("#queryTypeInput").autocomplete({
source: function (request, response) {
$.post("Dashboard/EnterMatterFormAjax", request, response);
},
select: function(event, ui){
$("#queryTypeInput").val(ui.item.value);
$("#enterMatterForm").submit();
}
});
I am trying to update a value in my database. When the user presses the update button this script is called.
View Code:
<script>
function scr_UpdateQuote(field) {
var r = confirm("Are you sure you want to update your quote?");
if (r == true) {
var textBox_UserTitle = document.getElementById(field);
*CODE TO POST METHOD HERE*
}
}
</script>
In the controller, the value is then revived and saved into the database. A message is sent back to let the user know their quote was updated.
Controller Code:
[HttpGet]
public ActionResult UpdateQuote(string newQuote)
{
*REPLACE QUOTE IN DATABASE*
ViewBag.QuoteUpdated = "Your Quote has been updated.";
return View();
}
I am having difficulty finding out how to write the code described between the **'s
(For the database part I have a user-id that can be used to identify the row)
You can use form posting like this:
$("#YourForm").submit(function() {
$.post("/YourController/UpdateQuote", $("#YourForm").serialize())
//this will serialize your form into:
// newQuote=someValue&&someOtherVariable=someOtherValue etc.
.done(function(data) {
// do what ever you want with the server response
});
})
or you can use an ajax post:
$.ajax({
type: "POST",
url: "/YourController/UpdateQuote",
data: {newQuote: document.getElementById(field)},
dataType: "json",
success: function(data) {
// do what ever you want with the server response
},
error: function(){
// error handling
}
});
For using the data, assuming you have an DbContext called MyDbContext:
[HttpGet]
public ActionResult UpdateQuote(string newQuote)
{
// get userID somehow, either from session, or pass as another parameter here
using (var dc = new MyDbContext)
{
var quoteToUpdate = dc.QuotesTable.FirstOrDefault(q => q.UserID == userID)
quoteToUpdate.quoteColumn = newQuote;
dc.SaveChanges();
}
ViewBag.QuoteUpdated = "Your Quote has been updated.";
return View();
}
On one ASP.NET page, I have a DataTable with a list of Investors. The client wanted a feature added that would allow their users to select individual investors from that list and and have an email button that would open up an email page and populate the bcc with the investor emails. So far, I have gotten the checkboxes implemented, and I am successfully going through the checkboxes and grabbing the emails of only the checked boxes. From this point, I am completely lost as to how to send that date over to the next page and have them fill into the bcc automatically. Here is my code so far:
<a onclick="grabEmail()" href="/Settings/EmailSelect" class="button blue" >Email Selected</a>
...
...
...
<script type="text/javascript">
function grabEmail() {
var emails = new Array();
var $checked = $('[#id=investoremails:checked');
$checked.each(function () {
emails.push($(this).val());
alert($(this).val()); //This was just to check to make sure emails
//were grabbed
}
);
$.ajax({
url: '/Settings/EmailSelect/',
type: "POST",
data: emails,
traditional: true,
});
}
Then, on EmailSelect page...
$(document).ready(function() {
$.ajax({
type: "GET",
url: "/Settings/EmailSelect",
error: function (xhr, status, error) {
$("#results").html("An error occurred: " + error).addClass("notification error");
return false;
},
success: function(response) {
if (response != null) {
if (!response.Successful) {
$("#results").html("An error occurred: " + response.Exception).addClass("notification error");
return false;
} else {
$("#bcc").val(response.ReturnVal);
}
}
}
});
});
And for the Controller..
public ActionResult EmailSelect(string[] emails)
{
ViewData["Selected"] = emails;
return View();
}
We have somewhat similar functionality in this program where Investors can be part of user created groups, and there's another email page where the user can select a specific group to email to, and I was trying to base the solution for this problem off that (even though they are inherently different..). If anyone can point me in the right direction, that would be great!
I should have answered this awhile ago, but I forgot to post it.
I did some research on MVC forms and how they interact with the controller, and I was easily able to get this to work by pulling the checkboxes in as a string array into the controller, and then passing them to the next page in ViewData.
For my company, we are building a web application for an invoicing system which utilises a notification bar, similar to that of Facebook, whereby the user can drop down a menu which displays the status of transactions on the system while a total number of outstanding transactions displays next to it. Please see the image for details.
http://img210.imageshack.us/img210/4379/alertdrop.png
We are retrieving the data for this using the following code for the table within the drop-down menu:
<table id="alertDropTable" style="margin-top:10px;">
#{
Dictionary<string, int> dic = ViewBag.statusCount;
if (dic != null)
{
for (int i = 0; i < dic.Count; i++)
{
if (dic.Values.ElementAt(i) > 0)
{
<tr>
<td width="100%" style="padding-bottom:4px; padding-top:4px; padding-left:10px; padding-right:10px; vertical-align:middle;">
You have <strong><a style="background-color:#878787; border-radius:5px; color:White; padding:3px;">#dic.Values.ElementAt(i)</a></strong> #dic.Keys.ElementAt(i) transaction(s).
</td>
</tr>
}
}
}
}
</table>
And the following for the span, which displays the total:
<div style="float: left;">
<img src="#Url.Content("~/Content/images/alert_notification.png")" name="alert" alt="alert"/>
#{
Dictionary<string, int> dicheader = ViewBag.statusCount;
int diccount = 0;
if (dicheader != null)
{
for (int i = 0; i < dicheader.Count; i++)
{
if (dicheader.Values.ElementAt(i) > 0)
{
diccount = diccount + #dicheader.Values.ElementAt(i);
}
}
}
}
</div>
<div id="alertTotalDiv" style="float:left;margin-top:6px; margin-left:5px;"><span id="alertTotal" style="vertical-align:middle; background-color:#878787; border-radius:5px; color:White; font-family:Georgia; font-size:20px; padding:3px; padding-left:5px; padding-right:5px;margin-top:0px;">#diccount</span></div>
This code is currently stored in the global "_layout.cshtml" file. Please excuse the roughness of the code, this is very much an early version. However, this is working fine in terms of retrieving the data on a page load. However, the system requires this information to be automatically updated every few seconds without refreshing the entire page. In essence, making a call to the controller to bring back the current data and update the <table> and <span> with the current values.
I have been asked to create an Ajax function which retrieves the data from the "AlertController" and updates the view accordingly. Please find the contents of this controller below:
public class AlertController : Controller
{
/// <summary>
/// Gets or sets the user service contract.
/// </summary>
/// <value>The user service contract.</value>
public IUserServiceContract UserServiceContract { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="BaseController"/> class.
/// </summary>
protected AlertController()
{
this.UserServiceContract = Gateway.Instance.Resolve<IUserServiceContract>();
}
/// <summary>
/// Get the AlertTypes
/// </summary>
/// <returns></returns>
public virtual void ViewAlerts()
{
Gateway.Instance.Logger.LogInfo(string.Format("Overview Controller View: Fetching list of alerts."));
try
{
if (this.UserServiceContract != null)
{
var allAnnouncements = this.UserServiceContract.GetAnnoucements();
var userAlertSettings = this.UserServiceContract.GetUserAlert();
ViewBag.statusCount = userAlertSettings;
ViewBag.announcements = allAnnouncements.ToList();
}
}
catch (Exception ex)
{
Gateway.Instance.Logger.LogInfo(ex);
throw new Exception(string.Format("Home Controller View Error: {0} occured while fetching alerts.", ex.Message), ex);
}
}
I am stumped, but have been given the following example of an Ajax function, which is used to perform a different task entirely, to aid me:
$.ajax({
url: '#Url.Action("ViewAlerts", "Alerts")',
data: { ownerIds: ownerIds },
traditional: true,
dataType: 'json',
success: function (result) {
for (i = 0; i < ownerIds.length; i++) {
$(".ownersTable tr[id='tablerow+" + ownerIds[i] + "']").remove();
}
},
error: function (xhr, ajaxOptions, thrownError) {
$("#confirmDiv").alertModal({
heading: '#Language.Fail',
body: '#Language.AlertRemoveOwnerFailed' + thrownError
});
}
});
Thus far, the only thing I've managed to get working was a set interval function, which makes an alert every 5 seconds!
Any guidance on this?
Okay, this is what you are going to need to do, first of all:
$.ajax({
url: '#Url.Action("ViewAlerts", "Alerts")',
data: { ownerIds: ownerIds },
traditional: true,
dataType: 'json',
success: function (result) {
for (i = 0; i < ownerIds.length; i++) {
$(".ownersTable tr[id='tablerow+" + ownerIds[i] + "']").remove();
}
},
error: function (xhr, ajaxOptions, thrownError) {
$("#confirmDiv").alertModal({
heading: '#Language.Fail',
body: '#Language.AlertRemoveOwnerFailed' + thrownError
});
}
});
Why is Url.Action in quotes? Just put #Url.Action ... I don't see a reason for the quotes and it may be breaking your call.
Second of all don't use ViewBag. It shouldn't be really used to hold 'data' (in my opinion). You should use a model. So this is what you can do:
Create the part of the page you want to update into a "Partial View" that is strongly typed to a model that contains the status and announcements and whatever else you need.
Use Jquery to 'Load' the Controller method that will get the data and return this 'Partial View', and load it into a Div on your screen example:
$('#div-to-load-into').load('/myactionurl/', function () { //Do something when done });
So your controller is then called, gets the data and returns the partial view with the model you created!
Good luck!
---Edit--- YOU should do above because it would be easier and faster (and if you do get to redesign you will quickly understand that, but here is an idea of how to do what you want)
This is what you need to know,
url is the action that the Ajax is going to call. You need to put url: '/controller/action'
data is the data you are sending to that action { parameter-name: parameter } it looks like in your case your sending no data because your only polling for a refresh, so you don't need to include this
dataType is the data you are expecting to be returned, it could be 'html' or 'json' , in your case your returning nothing because your using the 'ViewBag'
success will be called if the ajax call was successfully called with no errors with the result of that in 'result', in your case you have no result, because your using the view bag.
Now I can't promise this will work because I have never tried it:
function(result)
{
var updated_values = #Html.Raw(Json.Encode(ViewBag.AlertStatus))
}
Inside your success function on the ajax try this, this may or may not work. I honestly don't know if the ViewBag will have the updated values or not. At this point you only need to replace the table values with your new ones! you'll have to do all that in javascript, and I suggest looking at functions like 'appendTo', 'replaceWith', 'html' ect that are in Jquery to figure out how to do that.
$.ajax({
url: 'controller/action',
success: function (result) {
var alert_info = #Html.Raw(Json.Encode(ViewBag.AlertStatus))
},
error: function (xhr, ajaxOptions, thrownError) {
//error handling
}
});
(function checkStatus() {
$.ajax({
url: '#Url.Action("ViewAlerts", "Alerts")',
data: { ownerIds: ownerIds },
traditional: true,
dataType: 'json',
success: function (result)
{
for (i = 0; i < ownerIds.length; i++)
{
$(".ownersTable tr[id='tablerow+" + ownerIds[i] + "']").remove();
}
},
complete: function() {
// Schedule the next request when the current one's complete
setTimeout(checkStatus, 5000);
}
});
})();
How to fire AJAX request Periodically?
In order to get data from an action to JavaScript, your action must return data. Right now your "action" is not really an action, as it returns void and sets ViewBag properties, which are not accessible from JavaScript. So your action needs to be something more like:
[HttpGet]
public ActionResult Alerts()
{
IEnumerable alerts;
// ...code which gets data into alerts
return JsonResult(alerts);
}
Obviously I don't know your domain, so I don't know how you would structure the data coming back, but the basics are there. The $.ajax call would point to the action route (in this case, probably '/Alert/Alerts'). The success function would have the data argument with the appropriate array of objects. From there you'd update your DOM with the data.