Calling a controller function from onchange event in html view - javascript

I'm a new c# developer and I have a dropdownlist populated with string dates formatted like this: "Jul 2017". There can be as many as 12 entries in the list.
When a user selects a date, I want to pass that selection to a controller method, convert it to a DateTime format and then use that date for further processing.
How do I pass the user selection to the controller so it can be converted and used? I've included commented out code below to show how I want to do the conversion. Getting the date to the controller is my challenge.
I've looked at similar questions on this site and they all seem overly complex (perhaps due to my naivete), but I was hoping for a more streamlined solution.
Html View Code
#Html.DropDownList("selectList", Model.ReverseMonthsLists())
View Model Code
public IEnumerable<SelectListItem> ReverseMonthsLists()
{
var selectListItems = GetDates()
.Select(_ => _.ToString("MMM yyyy"))
.Select((dateString, index) => new SelectListItem
{ Selected = index == 0, Text = dateString, Value = dateString })
.ToList();
return selectListItems;
}
public static IEnumerable<DateTime> GetDates()
{
DateTime startDate = new DateTime(2017, 6, 1).Date;
var currentDate = DateTime.Now.Date;
int numberOfMonthsToShow = (currentDate.Year - startDate.Year) * 12 +
currentDate.Month - startDate.Month;
var dates = new List<DateTime>(numberOfMonthsToShow);
currentDate = currentDate.AddMonths(-1);
for (int i = 0; i < numberOfMonthsToShow; i++)
{
dates.Add(currentDate);
currentDate = currentDate.AddMonths(-1);
}
return dates;
}
Controller function
public ActionResult Report_Performance()
{
//var newDate = DateTime.Parse(strDate); //<- Use newDate as parameter value into aVar to replace date at the end of the string
var aVar = Models.Reporting.ListingStatsReportingViewModel.GetStats(userCurrentService.CompanyId.Value, Models.Reporting.DateTimePeriod.Monthly, DateTime.Now.Date.AddMonths(-1));
return this.View(aVar);
}

The normal way to get a value to a controller is for the user to post the page back to the server, e.g. via a submit button. When this happens, the controller's action method can receive the selected item as an argument and then do what it needs to do. So if you just want the user to submit the form, and allow the web site to render the next page based on the selected value (and a list that you compute based on that value), that is all you need to do.
On the other hand, perhaps you don't want the user to submit the page; you want a series of dates to be displayed within the page, or for the dates to be processed by code running in the browser. If that is the case, I would suggest you perform the computations in Javascript within the browser itself, thereby avoiding the need for a round trip. Nothing in your GetDates() method requires any server side data, so it's just a question of converting your c# code to Javascript code.
In some rare cases, you will want a UX element on the page to get updated immediately based on a server computation, without the page being posted. If that is what you want, you'll have to use the AJAX solutions the other posters have provided. It's much more complicated and much more work. If you don't need that, use one of the solutions I provided above.

You Can Use The OnChange EventHandler For The HTML Select Option
(The DropDownList ) To Start An Ajax Call To Your Controller , Simply Create a JavaScript Function That Preforms a Jquery Ajax Request Containing The User Selected Data To The Controller and Retrieve JSON From The Controller Using Return Json() Instead Of Return View() , Then Handle The Retrieved Data Using JavaScript , Your Controller Will Need To Accept a Parameter In Order To Receive The Data From The Ajax Request

function SendDataToController (TheDropDownName){
var DataToSend = $('#'+TheDropDownName).text();
// Or Pass `this` From The Html When Assigning The Event Listener
// and Do Something Like var DataToSend = this.text();
$.ajax({
url: "#(Url.Action("ActionName", "ControllerName"))",
data: DataToSend,
success: function(ResponseFromController){
//Do Stuff With Response
}
});
}
This Will Send The Data To Controller So You Should Receive It in A Parameter
public ActionResult MyAction (string DataToSend)
{
//Do Stuff With Data and Get a Json Object To Return
Return Json(JsonObject);
}
MVC Ajax Is Essential So You Should Learn It Before Tryin To Work On Any MVC Project, Also You Should Handle Request Error Using fail attr in The Ajax Setting But I Will Leave That To You

Related

Getting parameters from query string

I am creating a web page using ASP.Net WebAPi, MVC and Knockout.
I have a normal MVC controller that loads the pages when I need them:
[Authorize]
public class AdminController : Controller
{
public ActionResult Clients()
{
return View();
}
public ActionResult ClientEdit(int? Id)
{
return View();
}
}
And once the page is loaded, my Knockout model takes care of the loading of the data. So, the 'Clients' controller simply loads a list of all clients. When on that screen, a user can click 'Edit' next to a client, and the page is navigated to the 'ClientEdit' controller, which takes an id.
So, my knockout click event looks like this in my knockout view model:
self.EditClick = function () {
if (this.ClientId && typeof this.ClientId !== 'undefined') {
window.location.href = "/Admin/ClientEdit/" + this.ClientId;
}
else
window.location.href = "/Admin/ClientEdit/";
}
(It handles the 'Create New' button and the edit button, hence the 'if')
Once I redirect, the MVC controller loads the page, and the URL is:
http://localhost:49389/Admin/ClientEdit/1
I then load the knockout model, and would like to make an API call to get the data...
After my page loads, I want to bind the view model to the page. Here's my view model at the moment:
function AdminClientEditor() {
var self = this;
self.Name = ko.observable("");
self.ContactName = ko.observable("");
ko.applyBindings(new AdminClientEditor(), $("#clienteditor")[0]);
So, I will create a $.get method that calls a webAPI method that will return me data based on the id. I just need to get the ID somehow.
But, how do I get the Id (In this case, '1', from the URL?
And, is this the right way to achieve what I am trying to do?
You can pass the id value to view via viewbag.
public ActionResult ClientEdit(int? Id)
{
ViewBag.ClientId=id;
return View();
}
and in the view's script section
var clientId="#ViewBag.ClientId";
alert(clientId);
// use this
If your javascript code which accesses this id value is inside a separate external js file, you may set this value to a js variable in your view and access it in your js file. Make sure to use namespacing to avoid global variable overwriting value issues.
So in your view
<script>
var myApp = myApp || {};
myApp.ClientId= "#ViewBag.ClientId";
</script>
<script src="~/Scripts/PageSpecificExternalJsFile.js"></script>
And in the PageSpecificExternalJsFile.js file,
var clientId=myApp.ClientId;
//use this as needed
I'm not sure if this is the best way, but you can get the ID from the URL by using JS:
var id = GetID();
function GetID() {
var href = location.href;
var results = href.split("/");
return results[results.length - 1];
}
I've come up with this solution which works, but I am unsure if it's the best way. It seems pretty good.
I created a MVC ViewModel class in my application code, called 'GenericParameteModel', which at the moment, has a single parameter, "Id".
I then modified my page loading MVC method:
public ActionResult ClientEdit(int? Id)
{
var mv = new GenericParameteModel { Id = Id };
return View(mv);
}
On my View page, I added the model 'GenericParameteModel' to the View.
I created a hidden field, called 'ClientId' on the view.
<input type="hidden" id="clientId" value="#model.Id">
Then, within my knockout view model, I check if $("#clientId").val() has a value. If so, I do the $.get call, using that value, and populate my view model.
In doing so, all my initial page loads from MVC will have the ability to you the GenericParameteModel, and it will be a pattern for other pages. As it's a model, I can add new fields as my application requires.
This seems to work well. I'm unsure if this is an acceptable way as I am new to this (MVC to load views and the Knockout/WebApi to get the data after loading). But it seems neat and manageable.

Set Session Variable In MVC View and DateTimePicker

How can i set a Session value in the MVC View from Javascript in a DateTimePicker?
I have this code:
if('#Session["Data"]'==""){
$('#datetimepicker').datepicker('setDate', startDate); #Session["Data"] = startDate;}
else { $('#datetimepicker').datepicker('setDate', '#Session["Data"]'); }
This code work fine but the code
#Session["Data"] = startDate;
not working. How can i save Data here?
Thank you to all
You're merging javascript and c# code.
You can't set the startDate (javascript) to Session (c#) because javascript runs on client side.
If startDate is equals to DateTime.Now it'll help you.
<script>
if('#Session["Data"]'===""){
$('#datetimepicker').datepicker('setDate', new Date());
#(Session["Data"] = DateTime.Now);
} else {
$('#datetimepicker').datepicker('setDate', '#Session["Data"]');
}
</script>
Your C# Code in your razor view gets executed in server. But your javascript code executes on client. So you cannot set a c# variable value inside your javascript like what you have in your question.
What you can do is make an ajax call to an endpoint and set the value in session there. So create an action method to handle the ajax call
[HttpPost]
public ActionResult SetDate(DateTime date)
{
// Set to session here
return Json( new { Status="Success"});
}
Now from your javascript code, use ajax to call this endpoint and pass the date value.
var startDate= "Read the date value here";
$.post("YourControllerName/SetDate", { date = startDate},function(r){
if(r.Status==="Success")
{
alert("Date is now in session")
}
});
You may consider using the Url.Action helper method to generate the path o the action method instead of hardcoding.

Form submitted to Web Api Get(string id) is repeated until ::ERR_CONNECTION_RESET

I have a Web Api site and I am trying to call a controller and have it return a zip file from the server. I submit a form to my Web Api site using javascript:
document.getElementById("downloadSettings").submit();
The action on the controller is defined as:
public HttpResponseMessage Get(string id)
The form being submitted has an input that has the expected value (id). I submit the form, the controller receives the call, performs the action (fetches the requested file as byte[]), and attempts to return the file like this:
using (System.IO.MemoryStream ms = new System.IO.MemoryStream(fileContents))
{
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StreamContent(ms);
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = "fileName.zip";
return response;
}
Simply running the code ends in me receiving an error - ERR_CONNECTION_RESET.
If I debug the Get action, what I see is - the moment the Get function finishes, a new thread arrives at the beginning of the function! There is no new call being made from the browser (the Network tab shows no new calls), and yet, the function is repeated several times over until suddenly it doesn't and on the client (browser) I get ERR_CONNECTION_RESET.
What is going on? How do I fix it? Am I doing something wrong in the way I am attempting to return the file?
Apparently, the problem was the using([...]).
Once I removed that from the MemoryStream, everything went swimmingly!
I still do wonder though... what was up with the repeat calls?

Visualforce page with JS remoting and jquery not working as expected

I am having an issue with a snippet of javascript on a VF page where I am hoping someone can enlighten me where the code is flawing. To give a small background, the VF page has a picklist and an input field that are read/updated by the JS. There is jquery code in the script to autcomplete the Product input text field by retrieving the list of possible matches from the controller (via remoting call). To downsize the result I pass in the pricebook Id and the lineType from the Line Type picklist. I am trying to get the linetype to execute the code on the onchange event so to "cache" the results before the user types them in the input field. In my soe so far the line type changing event is firing the code and based on the alerts, I can see that the method in the controller is getting called and returns the list, BUT there are 2 issues on the result:
1) The .change event is not firing more than once, so the first time I cahnge the picklist value, the code fires and executes the remoting call, but any subsequent change to the picklist is not firing the code again. Why is that? shouldn't the .change always fire when changes are made to the selection of the picklist?
2) The autocomplete is not suggesting values based on the reusult from the call, meaning I don't see the pop up with the suggestions returned from the remoting call.
Below is the relevant code (VF page, js and controller method). please someone give me a hand!
VF + js code:
<script>
var pop, prodNames, pbId, lineType, availableProds;
$j = jQuery.noConflict();
$j(function() {
$j("select[id$='fLineType']").change(function() {
pbId = $j("input[id$='pbid']").val();
lineType = $j(this).val();
alert('Line type selected' + $j(this).val() + ' - ' + pbId );
// call remote apex method and get chache list of Prod Names:
SalesDocumentManager_Controller.cacheProdNames(pbId, lineType,
function(result, event){
alert('Result from remote call: ' + result);
availableProds = result;
},
{escape: true}
);
});
$j("input[id$='prodName']").autocomplete({
source: availableProds,
minLength: 3
});
});
controller remote method (currently returning dummy data):
//This seems to work since it returns the values created below:
#RemoteAction
public static String[] cacheProdNames (String pbId, String lineType) {
system.debug('###remote action is executing');
String[] prodNames = new List<String>();
prodNames.add('testProd');
prodNames.add('testProd 2');
return prodNames;
}

Send JS object to JSP page [duplicate]

This question already has answers here:
Call Servlet and invoke Java code from JavaScript along with parameters
(3 answers)
Closed 6 years ago.
I have a JS object in a JavaScript file. I have to pass this object to a JSP page. The page picks up this object and processes it. How can I do it?
The same way you get any other data from a web browser to an HTTP server.
Encode it in an HTTP request by submitting a form / setting the window location / using XMLHttpRequest / etc.
There are a couple of issues you need to resolve first, are you doing this in an AJAX style of request? is this a form submission? is there going to be on-going interaction within the page-session between the client/server passing JSON objects back-and-forth?
Lets tackle the simple case of a form submission, once you get that you should be able to get the remaining cases going as they are just "extensions" of this base case. Say you have some form that will submit the data in some field:
<form name='my_form' id='my_ford_id'>
<input type='hidden' name='my_input_field' />
</form>
then at some point in time you have a piece of code that executes and you have your JSON object
function myFunction() {
var json_data = getJsonData();
document.forms['my_form']['my_input_field'].value = json_data;
document.forms['my_form'].submit();
}
You will then on the JSP side receive this data as a JSON string inside of a form field, at which point you need to process it, lets assume you have some kind of a JSON library available to you, the code might look something like this:
<%
String myInputField = request.getParameter("my_input_field");
if(myInputField != null) {
try {
JSONObject myObject = new JSONObject(myInputField);
}
catch(JSONException e) {
}
}
%>
If you need an "AJAX" style of interaction, you will be making a number of such requests in the page, but fundamentally it falls back to the original problem of submitting the data. Since you are using forms in this example, and JSP, you don't have to worry at any point about encoding, the browser/server will take care of things for you.
When you send json object the servlet receive it in the same way of receiving data sent by submitting the form, for example, if you send a variable "action" with value="getCountries"
var option = {
"action": "getCountries"
};
$.getJSON('YourServlet', option, function() {
//hadle the result returned by servlet
});
The defualt method is GET, in the servlet you handle the request as you handle a normal request
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String action = request.getParameter("action");
if (action != null) {
if (action.equals("getCountries")) {
List coutries = getAllICountries(request); //get the countries
String json = new Gson().toJson(coutries);
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
response.getWriter().write(json);
return;
}
}
}
Notice how we return the result from servlet to javascript, we return a json object.
"JSON" Site helps you to manage Json Objects in JSp/java.
You have to convert the string obtained from javascript to a json object.Then manage it easily.

Categories

Resources