How to access a model property from seperate javascript file? (MVC) - javascript

Right now I am using a model property in the javascript as one of the values in a json object that i pass to the controller. The problem is that the javascript will be seperated in a .js file and will not be able to access #Model. So the question is; how do i access model from a seperated .js file?

You can load the external javascript as usual and the send the model value as a property to an init method like this in your view:
<script type="text/url" src="externalscript.js"/>
<script type="text/javascript">
$(function() {
var model = home.views();
model.init({
modelProperty: '#Model.Property',
});
</script>
And then your externalscript.js looks like:
(function (window) {
home = window.home || {};
home.views = function () {
pub.init = function (options) {
var property = options.modelProperty;
};
return pub;
})(window);
And you can use your property like you want to in the external script.

You could try RazorJs (unfortunatelly seems no more mantained)
Write Razor-Style C# or VB.NET inside your Javascript Files. Also
contains an http handler for serving, when needed, those files.
You could do something like this:
Views/Home
#{
ViewBag.Title = "Home Page";
}
#Html.RazorJSInclude("~/Scripts/App/TestRazorJS.js")
<button id="btnSearch" name="submit" type="button" onclick="LoadFromRazor()">Search</button>
Scripts / App / TestRazorJS.js
function LoadFromRazor() {
$.ajax({
url: '#Url.Action("Test", "Home")',
datatype: 'json',
type: 'GET',
cache: false,
success: function () { console.log('done'); },
error: function (xhr, status, error) {
console.log(status);
}
});
}

Related

ASP.Net MVC model binding to javascript

The question is pretty straightforward: I use #Html.EditorForModel() to generate fields for my model. Then user fills all these fields and I want to send this field via AJAX, becuase I should do several server's services without page reload.
I googled several approaches, but it seems that there is no standard way to do such things. I mean I do not have an object on client-side that represent model. I found one single library calls JSModel (link) but it seems to be not working. My code for now is:
#model Student
<script src="#Url.Content("~/scripts/jquery-1.12.2.min.js")" type="text/javascript" async="async"></script>
<script src="#Url.Content("~/scripts/Requester.js")" type="text/javascript" async="async"></script>
<script src="#Url.Content("~/scripts/jsmodel.js")" type="text/javascript"></script>
<script type="text/javascript">
var requester = new Requester(#Html.Raw(Json.Encode(new Student())));
function SendSignupRequest() {
requester.SendSignupRequest();
}
</script>
<h2>Student</h2>
<div>
#Html.EditorForModel()
</div>
<input type="button" value="Send" onclick="SendSignupRequest()"/>
Requester.js:
function Requester(rawModel) {
this.modelObj = new JSModel(rawModel);
this.SendSignupRequest = function() {
var model = modelObj.refresh();
var val = model.prop("Name");
alert(val);
}
}
Is there any easy way to serialize a model object in JSON and send it to server, without manually constructing an object with millions of document.getElementById?
View
#using (Html.BeginForm("action", "controller", FormMethod.Post, new { #class = "form-horizontal form-compact ", role = "form", id = "form1" }))
{
}
Java Script
var formdata = $("#form1").serializeArray();
$.ajax({
url: url,
type: 'POST',
data: formdata,
success: function (data) {
}
Controller
public ActionResult action(Model model)
{
//access data here
}
You can serialize your form to a JSON object with jQuery:
var data = $('form').serialize();
(This would, of course, mean wrapping your form elements in a form, which really should be happening anyway.)
Then just pass that data object to the server in the POST request. Something as simple as:
$.post('some/url', data, function(response) {
// success callback
});
without manually constructing an object with millions of document.getElementById
Note that if your object has millions of fields then you may very well encounter other problems here.
Yes you can use form serialize using Jquery
var formData = $('#form').serializeObject();
$.extend(formData, { Contacts : myContacts});
$.extend(formData, { Address : myAddress});
var result = JSON.stringify(formData);
$('#formHiddenField').val(result);
then submit form using:
$.ajax(
url: #Url.Action("post url")
data: myForm.serialize(),
dataType: 'json',
type: 'POST',
success: function(){
})
Why not Ajax.BeginForm() for your purposes. I believe model binding works automatically.

Transfer Data from ASP:NET MVC Controller to view

I have an object in contrroller and I want to use them in view and in javascript code but I can't achived using ViewBag. my code hear :
public class MyController : Controller
{
public async Task<ActionResult> Index()
{
using (var client = new HttpClient())
{
string response = await client.GetStringAsync("http://api/controller/....");
ViewBag.VB = response;
return View();
}
}
}
and my view :
#{
ViewBag.Title = "Index";
}
#section Javacript
{
<script type="text/javascript">
function MyFunction() {
**** //I want to use DATA hear. *********
};
</script>
}
<div id="info">
</div>
How can I do this? Anyone have an idea?
You can put your data into a <script type="text/html"> node and access it from javascript via document.getElementById
<script type="text/html" id="data">#ViewBag.VB</script>
<script>
function MyFunction() {
var data = document.getElementById('data').innerHTML;
// if the data is in the json format, you can use JSON.parse:
data = JSON.parse(data);
// TODO: do something with data
}
</script>
You can also insert the data directly into javascript:
function MyFunction() {
var data = '#(ViewBag.VB)'; // or omit the single quotes if it's json data
// TODO: do something with data
}
This approach requires that the javascript code is embedded into the .cshtml file.
Another possibility is to retrieve the data directly from javascript with an ajax request. This example uses jQuery's $.ajax function:
function MyFunction() {
$.ajax({
url: "/api/controller/...",
contentType: "application/json", // tell the api-controller that we want json
dataType: "application/json", // tell the jQuery callback that it is json
success: function (data) {
// TODO: do something with data
}
});
}

How to bind a controls data using jQuery and Static Page Method?

Goal: Call a server side method asynchronously from changing a dropdown to get data and populate a separate listbox not using UpdatePanels.
Currently I'm using a static ASP.NET page method asynchronously using jQuery and an ajax call as shown in this post (How to wire up a DropDownList to make AJAX calls to the server?) and it is working well.
The whole purpose was to prevent using the UpdatePanel tangled mess that I had been in previous years and this seems to be a good alternative. What I didn't realize is that the page method has to be static and you can not access any of the page's controls or context. So trying to make this call from a dropdown selection to populate another control's data is not possible. I can't see the other controls.
So what I'd like to do before I give up and go back to updatepanels is try to do 1 of the following:
Have my static page method return a json string with my collection data that I then use in the original jQuery method wired up to the change method of the dropdown to populate the separate listbox.
Same as above but return a .NET IList<> or comparable if returning json is not a good idea.
Point is I want that static method to return the needed data to bind to my listbox control. However I don't know how to do this. Here is my current jQuery method:
<script type="text/javascript">
$(document).ready(function () {
// Add the page method call as an onclick handler for the control.
$("<%= MyDDL.ClientID %>").click(function () {
$.ajax({
type: "POST",
url: "Default.aspx/MyDDL_SelectedIndexChanged",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json"
});
});
});
</script>
Here is the original dropdown:
<asp:DropDownList ID="MyDDL" runat="server" Width="340px" />
Here is the control that needs populated based on the selection of the dropdown after calling the static method named MyDDL_SelectedIndexChanged:
<asp:ListBox ID="ListBox2" runat="server" Width="340px" SelectionMode="Multiple" />
Here is my current static page method:
[WebMethod]
public static string MyDDL_SelectedIndexChanged()
{
var myClass = new MyClass()
var data = myClass.GetDataCollection()
JavaScriptSerializer serializer = new JavaScriptSerializer();
string jsonString = serializer.Serialize(data);
}
Is there a way to take this returned data and bind it in the jQuery method above? My bailout is to go back to using an UpdatePanel where my server-side method can access other controls, but I really do not want to do this.
There is a javascript project called jsRender that may be what you need:
http://weblogs.asp.net/stevewellens/archive/2011/12/01/goodby-jquery-templates-hello-jsrender.aspx
I actually was looking for a more complete exaample and have the solution working with the code below:
$(document).ready(function () {
MyDDL_OnChangeHandler();
});
function MyDDL_OnChangeHandler() {
// Add the page method call as an change handler for the MyDDL DropDownList.
// This will call the static page method, and use the returned results to populate the 'MyListBox' listbox control.
$('#<%=MyDDL.ClientID %>').change(function () {
var val = $(this).val();
var text = $(this).children("option:selected").text();
var $lbxCtrl = $('#<%=MyListBox.ClientID %>');
$lbxCtrl.attr('disabled', 'disabled');
$lbxCtrl.empty();
$lbxCtrl.append('<option value="0">< Loading Please Wait... ></option>');
$.ajax({
type: "POST",
url: "Default.aspx/MyDDL_SelectedIndexChanged",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: "{'ID':'" + val + "', 'Name':'" + text + "'}",
success: function (data) {
$lbxCtrl.removeAttr('disabled');
$lbxCtrl.empty();
if (data.d == null) {
return;
}
$.each(data.d, function (i, data) {
$users.append('<option value="' + data.Value + '">' + data.FullName + ' (' + adUser.data+ ')' +'</option>');
});
},
error: function () {
$lbxCtrl.empty();
$lbxCtrl.append('<option value="0">< Error Loading Data ></option>');
alert('Failed to retrieve data.');
}
});
});
As Michael B mentioned in the comments, you can handle any data returned from the ajax call by using success:
<script type="text/javascript">
$(document).ready(function () {
// Add the page method call as an onclick handler for the control.
$("#<%= MyDDL.ClientID %>").click(function () {
$.ajax({
type: "POST",
url: "Default.aspx/MyDDL_SelectedIndexChanged",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data) {
// do stuff with the "data" that is returned
},
error: function(data) {
// handle any errors here
}
});
});
});
</script>

Url.Content for javascript

I currently use this approach to obtain the correct relative URI (independent of the deployment situation). Razor code (asp.net mvc 3):
#section JavaScript
{
<script type="text/javascript">
var _getUrl = "#Url.Content("~/bla/di/bla")";
</script>
}
Separate js file:
$.ajax({
url: _getUrl,
Do you reckon there is a better approach?
Personally I prefer using HTML5 data-* attributes or including the URL as part of some DOM element that I unobtrusively AJAXify.
The thing is that you never write $.ajax calls flying around like that. You write them to correspond to some DOM events. Like for example clicking of an anchor. In this case it's trivial, you just use an HTML helper to generate this anchor:
#Html.ActionLink("click me", "someAction", "somecontroller", new { id = "123" }, new { #class = "link" })
and then:
$('.link').click(function() {
$.ajax({
url: this.href,
type: 'GET',
success: function(result) {
...
}
});
return false;
});
or maybe you are AJAXifying a form:
#using (Html.BeginForm("SomeAction", "SomeController", FormMethod.Post, new { id = "myForm" }))
{
...
}
and then:
$('#myForm').submit(function() {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function(result) {
...
}
});
return false;
});
Another example would be to use HTML5 data-* attributes when an appropriate url is not available on the corresponding DOM element. Suppose that you want to invoke a controller action with AJAX when the selection of a dropdown changes. Think for example cascading ddls.
Here's how your dropdown might look like:
#Html.DropDownListFor(x => x.SelectedValue, Model.Values, new { id = "myDdl", data_url = Url.Action("SomeAction") })
and then:
$('#myDdl').change(function() {
var url = $(this).data('url');
var selectedValue = $(this).val();
$.getJSON(url, { id: selectedValue }, function(result) {
...
});
});
So as you can see you don't really need this _getUrl global javascript variable that you declared in your view.
I would do the following:
Razor C# script before Javascript
#{
var myUrlString = Url.Action("ActionName", new { controller="ControllerName" });
}
JavaScript
$.ajax('#myUrlString',{
// options
});
You could also use Url.RouteUrl or Url.HttpRouteUrl.
EDIT - showing example with separated JS file
Razor
#{
var myServerGeneratedValue = Url.Action("ActionName", new{controller="ControllerName"});
}
<script type="text/javascript">
var myHelperObject = new MyHelperObject();
myHelperObject.Init('#myServerGeneratedValue');
</script>
JS file
var MyHelperObject = function(){
this.Init = function(serverGeneratedValue){
// do something with serverGeneratedValue
};
};

Calling ASP.NET MVC Action Methods from JavaScript

I have sample code like this:
<div class="cart">
<a onclick="addToCart('#Model.productId');" class="button"><span>Add to Cart</span></a>
</div>
<div class="wishlist">
<a onclick="addToWishList('#Model.productId');">Add to Wish List</a>
</div>
<div class="compare">
<a onclick="addToCompare('#Model.productId');">Add to Compare</a>
</div>
How can I write JavaScript code to call the controller action method?
Use jQuery ajax:
function AddToCart(id)
{
$.ajax({
url: 'urlToController',
data: { id: id }
}).done(function() {
alert('Added');
});
}
http://api.jquery.com/jQuery.ajax/
Simply call your Action Method by using Javascript as shown below:
var id = model.Id; //if you want to pass an Id parameter
window.location.href = '#Url.Action("Action", "Controller")/' + id;
You are calling the addToCart method and passing the product id. Now you may use jQuery ajax to pass that data to your server side action method.d
jQuery post is the short version of jQuery ajax.
function addToCart(id)
{
$.post('#Url.Action("Add","Cart")',{id:id } function(data) {
//do whatever with the result.
});
}
If you want more options like success callbacks and error handling, use jQuery ajax,
function addToCart(id)
{
$.ajax({
url: '#Url.Action("Add","Cart")',
data: { id: id },
success: function(data){
//call is successfully completed and we got result in data
},
error:function (xhr, ajaxOptions, thrownError){
//some errror, some show err msg to user and log the error
alert(xhr.responseText);
}
});
}
When making ajax calls, I strongly recommend using the Html helper method such as Url.Action to generate the path to your action methods.
This will work if your code is in a razor view because Url.Action will be executed by razor at server side and that c# expression will be replaced with the correct relative path. But if you are using your jQuery code in your external js file, You may consider the approach mentioned in this answer.
If you do not need much customization and seek for simpleness, you can do it with built-in way - AjaxExtensions.ActionLink method.
<div class="cart">
#Ajax.ActionLink("Add To Cart", "AddToCart", new { productId = Model.productId }, new AjaxOptions() { HttpMethod = "Post" });
</div>
That MSDN link is must-read for all the possible overloads of this method and parameters of AjaxOptions class. Actually, you can use confirmation, change http method, set OnSuccess and OnFailure clients scripts and so on
If you want to call an action from your JavaScript, one way is to embed your JavaScript code, inside your view (.cshtml file for example), and then, use Razor, to create a URL of that action:
$(function(){
$('#sampleDiv').click(function(){
/*
While this code is JavaScript, but because it's embedded inside
a cshtml file, we can use Razor, and create the URL of the action
Don't forget to add '' around the url because it has to become a
valid string in the final webpage
*/
var url = '#Url.Action("ActionName", "Controller")';
});
});
Javascript Function
function AddToCart(id) {
$.ajax({
url: '#Url.Action("AddToCart", "ControllerName")',
type: 'GET',
dataType: 'json',
cache: false,
data: { 'id': id },
success: function (results) {
alert(results)
},
error: function () {
alert('Error occured');
}
});
}
Controller Method to call
[HttpGet]
public JsonResult AddToCart(string id)
{
string newId = id;
return Json(newId, JsonRequestBehavior.AllowGet);
}
You can simply add this when you are using same controller to redirect
var url = "YourActionName?parameterName=" + parameterValue;
window.location.href = url;
You can set up your element with
value="#model.productId"
and
onclick= addToWishList(this.value);
I am using this way, and worked perfectly:
//call controller funcntion from js
function insertDB(username,phone,email,code,filename) {
var formdata = new FormData(); //FormData object
//Iterating through each files selected in fileInput
formdata.append("username", username);
formdata.append("phone", phone);
formdata.append("email", email);
formdata.append("code", code);
formdata.append("filename", filename);
//Creating an XMLHttpRequest and sending
var xhr = new XMLHttpRequest();
xhr.open('POST', '/Home/InsertToDB');//controller/action
xhr.send(formdata);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
//if success
}
}
}
in Controller:
public void InsertToDB(string username, string phone, string email, string code, string filename)
{
//this.resumeRepository.Entity.Create(
// new Resume
// {
// }
// );
var resume_results = Request.Form.Keys;
resume_results.Add("");
}
you can find the keys (Request.Form.Keys), or use it directly from parameters.
You can easily make a <a> link in your view.
<a hidden asp-controller="Home" asp-action="Privacy" id="link"></a>
then in you javascript code use this:
location.href = document.getElementById('link').href;

Categories