Converting a Webform application to MVC - javascript

I am converting an ASP.NET WebForm application into an ASP.NET MVC application and being new to MVC, I am trying to make sure I do this right.
Currently, in my WebForm application, it is AJAX powered using jQuery and doing calls to WebMethods in the C# code behind. Currently, how the WebForm works now is there might a page with a few fields that need to be filled out and saved to the database. To do this, we'd have an HTML form and a save button. When the button is pressed, this javascript function is called:
function SaveForm()
{
if (!ValidateForm())
return;
ShowWaitingOverlay();
var params = {};
params.firstName = $('#<%= txtFirstName.ClientID %>').val();
params.lastName = $('#<%= txtLastName.ClientID %>').val();
params.address1 = $('#<%= txtAddress1.ClientID %>').val();
params.address2 = $('#<%= txtAddress2.ClientID %>').val();
// ... many more just like above
$.ajax({
type: "POST",
url: "Hosts.aspx/SaveHost",
data: params,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
HideWaitingOverlay();
if (msg.d == "0") {
alert("Save Failed!");
}
}
});
}
This function would do an AJAX call to an ASP.NET Web Method that might look similar to this:
[WebMethod]
public static string SaveForm(string firstName, string lastName, string address1, string address2)
{
var host = new BusinessLayer.HostApplication();
host.FirstName = firstName;
host.LastName = lastName;
host.Address1 = address1;
host.Address2 = address2;
host.Save();
return host.HostId.ToString();
}
Of course there are other irrelevant details omitted for brevity, but this is the general idea.
My question is, what would be the correct "MVC way" of converting this? I would think a lot of this code would go away and/or be hidden in the data model. I wouldn't think it would be necessary to have to need all the lines that assign each individual textbox/dropdown, etc to the params variable.

You could have an action method that get a DTO object and returns a Json result. In this action method, you could call the business layer to proceed the flow. For sample:
[HttpPost]
public ActionResult SaveForm(CustomerDTO input)
{
var host = new BusinessLayer.HostApplication();
host.FirstName = input.FirstName;
// oth properties
host.Save();
return Json(new {success = host.HostId != 0});
}
and your DTO could be:
public class CustomerDTO
{
public string FirstName { get; set; }
// other properties
}
In the client-side, you could try this:
$.ajax({
type: "POST",
url: "#Url.Action("SaveForm", "ControllerName")",
data: $("#formId").serialize(),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(result) {
if (result.success)
{
HideWaitingOverlay();
}
else
{
alert("Save Failed!");
}
}
});

Related

Why this JQuery function just works with post?

Why this JQuery function works with post? But not with get? I don't want to change anything in my database just to return some information...It seems that like I am passing parameters it just recognize type: post in Ajax even if my intention is not to change anything. If I don't use type:"post" my parameter in the controller action is going to be null.
$(document).ready(function () {
$(".link").click(function () {
var grad = $(".link").data("graduate")
$.ajax({
type: "post",
url: $(".link").data("url"),
data: JSON.stringify( { graduate: grad }),
contentType: "application/json; charset=utf-8"
})
$("#myModal").modal("show");
})
})
This is my controller:
public ActionResult PopulateModal(CMIPGraduateVM graduate)
{
return PartialView(graduate);
}
You can send data in the body of a POST request. You can only pass data with a GET request by using URL parameters, e.g. url.com?this=that&so=on
Add [HttpPost] to your controller method to allow it to accept posted data.
[HttpPost]
public ActionResult PopulateModal(CMIPGraduateVM graduate)
{
return PartialView(graduate);
}
And CMIPGraduateVM needs to be a class that has the graduate property whose type matches the structure that you're providing with the grad variable (var grad = $(".link").data("graduate"); not sure if this is a string or bool or object, etc).

How to call a function in another MVC controller using AJAX in Jquery

My folder structure looks like this. Both of these folders are contained within the Area folder.
I am trying to call a function from the EmailController inside ITRequests/Scripts/Edit.js and it fails to find it.
The .js code look likes this
$(document).on('change', '#StatusId', function (event) {
event.preventDefault();
debugger;
if(( $('#OldStatus').val() ) != ( $('#StatusId').val()) ) //Aka if the user switched the status on submit
{
var status_description = [$('#OldStatus').val(), $('#StatusId').val()];
$.ajax({
url: "/Email/Email/statusChangeEmail",
type: 'POST',
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ 'request': $('#RequestId').val(), 'status_descriptions': status_description }),
done: function (data) {
debugger;
alert("working");
}
})
}
})
RequestId is a hidden value on the page which is being picked up correctly, likewise the status_description field is taking the correct values and (tries to) pass them to the function.
The function EmailController.cs is defined as such
[HttpPost]
public ActionResult statusChangeEmail(int request, string[] status_descriptions)
{
//stuff happens
return Json(1);
}
However every time this happens I get this error message
Why your URL is /Email/Email/statusChangeEmail? It should be /Email/statusChangeEmail.
The /Email means EmailController and /statusChangeEmail means controller action statusChangeEmail .

Calling a HTTP POST method in a MVC Controller from the View's Javascript & Database saving

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();
}

Get ServerDateTime from client side

I Have a javascript client side function to set the DateTime function.
function SetDateTime()
{
var presentDate = new Date();
}
Instead I like to get the date from server side whenever SetDateTime() function is called.
in .cs I have this method to return server time.
[System.Web.Services.WebMethod]
protected static string GetCurrentTime()
{
HiddenField hdnCurrentDateTime = new HiddenField();
hdnCurrentDateTime.Value = DateTime.Now.ToString();
return hdnCurrentDateTime.Value;
}
How to access this method from client side javascript? Thank you for your time.
using ajax call we can call webmethod like this
$.ajax({
type: "Post",
url: "pagename/GetCurrentTime",
contentType: "application/json",
dataType: "json",
success: function (data) {
alert(data);
}
}
});
As your method is static and assuming you have hdDate in your page, try this:
<asp:HiddenField ID="hdDate" runat="server"
value="<%# YourClassName.GetCurrentTime()%>" />

Can't send array from jQuery to MVC 4 controller

I've googled this up and checked all over StackOverflow but I must be missing something... I have unobtrusive jQuery that hijaks a simple button click. It counts up the checkboxes and adds each checked boxes value to an array. The list is correct when I use an alert box in jQuery but the array never makes it to the controller side. The code flows to the controller but I break on var resolutionViewModel=new ResolutionViewModel(); and check trans - the argument is null. I'm new to jQuery and could really use the help here.
jQuery
// Return the selected transactions
function resolveTransactions() {
$('#btnResolve').click(function() {
var selectedTransactions = new Array();
$('input[name="chkTransaction"]:checked').each(function() {
selectedTransactions.push(this.value);
});
if (selectedTransactions.length > 0) {
$.ajax({
type: 'POST',
dataType: 'json',
url: 'http://localhost/AuditLog/Home/ResolutionFormDisplay',
contentType: 'application/json; charset=utf-8',
data: {trans : selectedTransactions},
traditional: true,
success: function (data) { alert(data); },
error: function(xhr, status, errorThrown) { alert("Error: " + errorThrown); }
});
}
});
};
Controller side
[HttpPost]
public PartialViewResult ResolutionFormDisplay(List<string> trans)
{
var resolutionViewModel = new ResolutionViewModel();
// fill Usernames dropdown selector in ViewModel
// fill Status dropdown selector in ViewModel
// fill list of transactionIds in ViewModel
return PartialView("_ResolutionDialog", resolutionViewModel);
}
Try having your controller accept a List, rather than just a single string (since you're not passing a single string):
[HttpPost]
public PartialViewResult ResolutionFormDisplay(List<string> value)
{
var resolutionViewModel = new ResolutionViewModel();
// fill Usernames dropdown selector in ViewModel
// fill Status dropdown selector in ViewModel
// fill list of transactionIds in ViewModel
return PartialView("_ResolutionDialog", resolutionViewModel);
}
Posted JSON needs to have named properties matching parameters in your controller method. Check the 'network' tab in Chrome dev tools and see exactly what you're posting, it's probably something like this:
"{\"value\":\"...\"}"
There is no value property to pass to your controller method's value parameter. I think the best would be just to get rid of the `JSON.stringify" and accept a list like Colin's answer, but if you want to take it as a string, the JSON string needs to be the value property of an object, not the other way around:
data: {value : JSON.stringify(selectedTransactions)},
Try passing your array as follows:
data:"{'trans':" + JSON.stringify(selectedTransactions)+"}"
Your method should be as follows:
public void Method(List<string> trans)
{
//Your implementation
}
SOLUTION:
The $.ajax postback was not sending properly formatted data to the controller. I discovered this by using the network tab in IE and looking at the Request Body of the POSTed http. It looked like this:transaction_table_length=10&chkTransaction=22&chkTransaction=23 -- It should have looked like this: {"trans":["22","23"]}. To solve this issue I stringified the property name and array as shown below, changed the dataType to 'text', and made the parameter on the controller action method take a String[] trans.
jQuery
// Return the selected transactions
function resolveTransactions() {
$('#btnResolve').click(function() {
var selectedTransactions = new Array();
$('input[name="chkTransaction"]:checked').each(function() {
selectedTransactions.push(this.value);
});
if (selectedTransactions.length > 0) {
$.ajax({
type: 'POST',
dataType: 'text',
url: 'http://localhost/AuditLog/Home/ResolutionFormDisplay',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({ trans:selectedTransactions }),
traditional: true,
success: function (data) { alert(data); },
error: function(xhr, status, errorThrown) { alert(" Error: " + errorThrown); }
});
} else {
alert('You must select (check) at least one transaction to apply a resolution.');
return false;
}
return false;
});
};
MVC 4 controller action
[HttpPost]
public PartialViewResult ResolutionFormDisplay(string[] trans)
{
var resolutionViewModel = new ResolutionViewModel();
// fill Usernames dropdown selector in ViewModel
// fill Status dropdown selector in ViewModel
// fill list of transactionIds in ViewModel
return PartialView("_ResolutionDialog", resolutionViewModel);
}

Categories

Resources