Asp.net mvc passing a C# object to Javascript - javascript

I have c# class say options more like AjaxOptions.
public class options
{
public string Url {get;set;}
public string httpMethod {get;set}
}
and a javascript function like this
function dosomething(obj)
{
if (obj.Url!="" and obj.HttpMethod=="something")
loadsomething();
}
Now in my Controller action
public class mycontroller : controller
{
public ActionResult WhatToDo()
{
options obj = new options{Url="someurl"};
return PartialView(obj);
}
}
in my view I need this object kind of string which i should be able to pass to my method.
#model options
<script>
dosomething(#model.SomeFunctionToConverToString())
</script>
So I need this SomeFunctionToConverToString method which i will convert this object to string.
Thanks

You should be able to use it like you would any other output of a model property in your view. Just reference the property that you want to pass in the JS function.
#model options
<script>
dosomething('#(model.Url)');
</script>
See this post for more information on using Razor inside of JS
EDIT - Something that might catch you is that if your URL get's broken from the HTML encoding that Razor does using the above, you can use the #Html.Raw() function which will pass the Url property without HTML encoding it.
<script>
dosomething('#Html.Raw(model.Url)');
</script>
EDIT 2 - And another SO post to the rescue! You are going to most likely want to convert your model to JSON in order to use in a Javascript function. So...in order to do that - you will need something in your view model to handle a JSON object.
public class optionsViewModel
{
public options Options{get;set;}
public string JsonData{get;set;}
}
and in your controller:
public class mycontroller : controller
{
public ActionResult WhatToDo()
{
options obj = new options{Url="someurl"};
var myViewModel = new optionsViewModel;
myViewModel.options = obj;
var serializer = new JavaScriptSerializer();
myViewModel.JsonData = serializer.Serialize(data);
return PartialView(myViewModel);
}
}
And finally the view:
#model optionsViewModel
<script>
dosomething('#model.JsonData')
</script>
Using this method, then your function will work as expected:
function dosomething(obj)
{
if (obj.Url!="" and obj.HttpMethod=="something")
loadsomething();
}
EDIT 3 Potentially the simplest way yet? Same premise as edit 2, however this is using the View to JsonEncode the model. There are probably some good arguments on either side whether this should be done in the view, controller, or repository/service layer. However, for doing the conversion in the view...
#model options
<script>
dosomething('#Html.Raw(Json.Encode(Model))');
</script>

Try this:
<script type="text/javascript">
var obj= #Html.Raw(Json.Encode(Model));
function dosomething(obj){}
</script>

That's work for me
Client side:
function GoWild(jsonData)
{
alert(jsonData);
}
Alert print :
{"wildDetails":{"Name":"Al","Id":1}}
MVC Razor Side:
#{var serializer new System.Web.Script.Serialization.JavaScriptSerializer();}
<div onclick="GoWild('#serializer.Serialize(Model.wildDetails)')"> Serialize It </div>

there is also a syntax error
<script type="text/javascript">
dosomething("#Model.Stringify()");
</script>
note the quotes around #Model.Stringify() are for javascript, so the emitted HTML will be:
<script type="text/javascript">
dosomething("this model has been stringified!");
</script>

I would recommend you have a look at SignalR, it allows for server triggered javascript callbacks.
See Scott H site for details: http://www.hanselman.com/blog/AsynchronousScalableWebApplicationsWithRealtimePersistentLongrunningConnectionsWithSignalR.aspx
In summary thou ...
Javascript Client:
var chat = $.connection.chat;
chat.name = prompt("What's your name?", "");
chat.receive = function(name, message){
$("#messages").append("
"+name+": "+message);
}
$("#send-button").click(function(){
chat.distribute($("#text-input").val());
});
Server:
public class Chat : Hub {
public void Distribute(string message) {
Clients.receive(Caller.name, message);
}
}
So .. Clients.receive in C# ends up triggering the chat.receive function in javascript.
It's also available via NuGet.

Related

Passing data from JavaScript code to the a Razor partial view within ASP.NET Core 3.1 MVC based application

Here are some details about our development environment:
-DevExpress 20.1.7 ( we are using DevExtreme )
-Microsoft Visual Studio Enterprise 2019 (Version 16.4.6)
-ASP.NET Core 3.1.0
I canNot do the following with JavaScript because the document javascript object is undefined inside the following razor code.
#await Html.PartialAsync("UpldPopupContentTmpltPartial", new
ViewDataDictionary(ViewData) { { "BookId",
document.getElementById("HiddenSelectedUploadDataType").Value } });
Could someone please give me a detailed explanation with sample code that will show me how I can pass the document.getElementById("HiddenSelectedUploadDataType").Value to the aforementioned partial view?
#yiyi-you Thank you for your detailed explanation within your answer.
However, I used the following line of code with #Html.Raw , but even though I'm practical if deadline dates for projects are really close, and I have to get stuff done, I still prefer the proper code implementation practices especially when it makes it easier for code reuse in the future and/or security and/or clarity:
#await Html.PartialAsync("UpldPopupContentTmpltPartial", new
ViewDataDictionary(ViewData) { { "BookId",
#Html.Raw("document.getElementById('HiddenSelectedUploadDataType').Value")}
});
Is the aforementioned code adhere to proper implementation practices? If yes or no then please do explain. Appreciate feedback. Thanks.
There are two solutions:
1.pass model data to Partial,here is a demo:
TestPartial.cshtml:
#model Model1
<input asp-for="HiddenSelectedUploadDataType" />
#await Html.PartialAsync("UpldPopupContentTmpltPartial", new ViewDataDictionary(ViewData) { { "BookId",Model.HiddenSelectedUploadDataType } })
Model1:
public class Model1
{
public string HiddenSelectedUploadDataType { get; set; }
}
UpldPopupContentTmpltPartial.cshtml:
<div>#ViewData["BookId"]</div>
result:
2.You can use ajax to pass document.getElementById("HiddenSelectedUploadDataType").Value to action,and action return partial view to view,here is a demo:
TestPartial.cshtml:
#model Model1
<input asp-for="HiddenSelectedUploadDataType" />
<div id="partial"></div>
#section scripts{
<script>
$(function () {
$.ajax({
url: '/TestSlick/GetPartial',
type: 'POST',
data: {
BookId: $("#HiddenSelectedUploadDataType").val()
},
success: function (data) {
$('#partial').html(data);
}
});
})
</script>
}
TestSlickController:
public IActionResult TestPartial() {
Model1 m = new Model1 { HiddenSelectedUploadDataType="sdsss"};
return View(m);
}
public IActionResult GetPartial(string BookId) {
ViewData["BookId"] = BookId;
return PartialView("UpldPopupContentTmpltPartial");
}
result:

Reload page based on a selection from drop down list MVC

I have a working solution, but I don't know how to reload the page after a certain ID is selected from the drop down list. My list is being populated from the DB. When I select it, I can see the ID and the corresponding data for it. However, there is no change on the screen.
Model class:
public List<Hello> getID()
{
var que = (from rel in db.Table1
select new Hello
{
ID = rel.R_ID
}).ToList();
return que;
}
public List<Hello> getStuff()
{
var que = (from wre in db.View
select new Hello
{
ID = wre.R_ID,
Summary = wre.Summary,
Description = wre.Description
}
}
getHello() is the same exact method as the getStuff(), just accepts a string ID parameter.
Controller class:
public ActionResult Index()
{
var model = test.getStuff();
ViewBag.IDs = new SelectList(test.getID(), "", "ID");
return View(model);
}
[HttpPost]
public JsonResult getDataBySelectedID(string selectedId)
{
var que = test.getHello(selectedId);
return Json(que, JsonRequestBehavior.AllowGet);
}
Partial_View Class:
<div class="container">
<table id="myTable" align="left">
<tr>
<th>#Html.DisplayNameFor(model => model.R_ID)</th>
<th>#Html.DisplayNameFor(model => model.Summary)</th>
<th>#Html.DisplayNameFor(model => model.Description)</th>
</tr>
#foreach (var item in Model)
{
<tr id="Home">
<td>#Html.DisplayFor(x => item.R_ID)</td>
<td>#Html.DisplayFor(x => item.Summary)</td>
<td>#Html.DisplayFor(x => item.Description)</td>
</tr>
}
</table>
</div>
View Class:
#Html.DropDownList("ID", ViewBag.IDs as SelectList)
<script>
$(document).ready(function () {
$("#ID").on("change", function () {
var selectedId = this.value;
var url = "/Sample/getDataBySelectedID";
$.ajax({
method: "POST",
dataType: "json",
url: url,
data: {
selectedId: selectedId
}
});
});
});
</script>
#foreach (var item in Model)
{
<tr>
<td>
#{Html.RenderPartial("Partial_Index", item);}
</td>
</tr>
}
How would I be able to reload the page with the selected value and its corresponding data?
Any help would be appreciated!
Thank you.
As described in the comments, you'll have to load your data into your page somehow. I recommend you do this through partial views.
1) Create a reusable Partial View
First, create a partial view that references your model. To do this, create a view as you normally would for your controller, and tick the "Partial View" option. Make sure to select your model in the model dropdown.
Then, move your .cshtml that references your model from your current view to your partial view. For example, if you have a table that lists out the fields of your model, you would cut the entire table into your partial view. You want to include the minimal amount of code needed in the partial view (aka, don't copy your entire view into it).
2) Reference the Partial View in your Current View
Now that you have your partial view set up, you should use it in your existing view to load the table. You should make sure this works first before continuing. You can use the #Html.RenderPartial(string ViewName, object Model) helper method to render it. Read more. So, you might place this line where your now-cut-code was: #RenderPartial("MyPartialView", model), where "MyPartialView" is the name of your partial view, and model is the model object that you want to pass into the partial view.
3) Add Methods to Render Partial View on Controller
At this point, you just need to be able to update your partial view after using AJAX. First, you need to add the ability to render the Partial View as a string so that you can easily inject it into your view. I recommend you do this by implementing a controller interface and letting your controller inherit the needed methods from that. In my programs, I have the following controller interface that my controllers inherit from:
public class IBaseController : Controller
{
internal string PartialViewToString(string partialViewName, object model = null)
{
ControllerContext controllerContext = new ControllerContext(Request.RequestContext, this);
return ViewToString(
controllerContext,
ViewEngines.Engines.FindPartialView(controllerContext, partialViewName) ?? throw new FileNotFoundException("Partial view cannot be found."),
model
);
}
protected string ViewToString(string viewName, object model = null)
{
ControllerContext controllerContext = new ControllerContext(Request.RequestContext, this);
return ViewToString(
controllerContext,
ViewEngines.Engines.FindView(controllerContext, viewName, null) ?? throw new FileNotFoundException("View cannot be found."),
model
);
}
protected string ViewToString(string viewName, string controllerName, string areaName, object model = null)
{
RouteData routeData = new RouteData();
routeData.Values.Add("controller", controllerName);
if (areaName != null)
{
routeData.Values.Add("Area", areaName);
routeData.DataTokens["area"] = areaName;
}
ControllerContext controllerContext = new ControllerContext(HttpContext, routeData, this);
return ViewToString(
controllerContext,
ViewEngines.Engines.FindView(controllerContext, viewName, null) ?? throw new FileNotFoundException("View cannot be found."),
model
);
}
private string ViewToString(ControllerContext controllerContext, ViewEngineResult viewEngineResult, object model)
{
using (StringWriter writer = new StringWriter())
{
ViewContext viewContext = new ViewContext(
ControllerContext,
viewEngineResult.View,
new ViewDataDictionary(model),
new TempDataDictionary(),
writer
);
viewEngineResult.View.Render(viewContext, writer);
return writer.ToString();
}
}
}
Then, on your controller you can inherit from this interface like so:
public class ExampleController : IBaseController
{
}
Now, you can use the new methods to easily render your partial view to a string.
In your getDataBySelectedID action, this is what you'll want to do.
[HttpPost]
public JsonResult getDataBySelectedID(string selectedId)
{
var que = test.getHello(selectedId);
string partialViewString = PartialViewToString("MyPartialView", que);
return Json(partialViewString, JsonRequestBehavior.AllowGet);
}
You may need to modify the above statement to fit your uses, but it should get you close.
4) Inject Partial View into Page on AJAX Success
Now, we've setup a Partial View to handle the model data that we want to update. We've updated our view to load from the Partial View by default. We've implemented a controller interface that will let use render that Partial View to a string so that we can inject it into our page. Now, we just need to do that injection.
First, wrap the previous setup #Html.RenderPartial() statement in a div. Let's give it the ID partialViewDiv. This will let us easily target it with jQuery.
$(document).ready(function () {
$("#ID").on("change", function () {
var selectedId = this.value;
var url = "/Sample/getDataBySelectedID";
var $partialViewDiv = $('#partialViewDiv');
$.ajax({
method: "POST",
dataType: "json",
url: url,
data: {
selectedId: selectedId
}
})
.done(function (response, status, jqxhr) {
$partialViewDiv.html(response);
// Do any other updates here.
})
.fail(function (reponse, status, error) {
$partialViewDiv.html('');
// Handle your error here.
});
});
});
Again, these is mostly pseudo-code so you may have to make some modifications. But, at this point, you should be roughly where you need to be. The AJAX call should update your view by reloading the partial view with your new model data.
Tips
Loading a partial view like this may break some jQuery event handlers, depending on your application. If that happens, take a look at this.
You can return any string from the Controller with your AJAX call. You could, if needed, return different partial views than what you originally loaded. Just use the methods from the interface and you can render whatever you need.
The above code is only some general guidelines. Without knowing your full implementation, I can't provide 100% working, bug free code. But, post here if you have any issues and I'll try to help.
A solution i see is with php
location.reload();
That is how you reload but if you want to reload with data you could use something like
window.location.replace("PathToThePage.php?YourDataName=YourData");

Why does java can't recognize html text after submtting to Spring controller?

I send js variable to Spring controller by clicking button.
That's what I have in js:
function submitArticle()
{
var pdata= $('textarea').froalaEditor('html.get');
$.post("/submitProject", pdata).done(function(response) {
console.log("Response: " + pdata);
});
}
So it works well, console.log displays next : <h1>New Article</h1><p>Some text</p>
but, that's what I get in Spring controller:
%3Ch1%3ENew+Article%3C%2Fh1%3E%3Cp%3ESome+text%3C%2Fp%3E=
It just replaces <, >, and / to some codes. How to replace them to normal tags. Because I want to store this html code in java String.
My Spring Controller:
#PostMapping("/submitProject")
public ModelAndView submitProject(#RequestBody String html, #ModelAttribute(value = "LoggedUser") User user)
{
System.out.println(html);
return new ModelAndView("redirect:/");
}
Check out the java.net.URLDecoder#decode method.
When I ran the code you posted through it I was able to retrieve the original text
Send as an object and receive a Map
$.post("/submitProject", {pdata})...
and
public ModelAndView submitProject(#RequestBody Map<String, String> data ...
// -> String html = data.get('pdata');

How to Get Model Object to Javascript variable

i have an action like below in my controller and the object of one Viewmodel class i had send as an argumnet to view. The problem is i need to get this object values in
javascript.
public ActionResult FillChecklist()
{
classOne objVM=new classone();
objVM.List=//get list
objVM.Id=//someid
objVM.List2=//secondlist
return View(objVM);
}
i had tried something like below but it does not works. i know hidden variable assign is a solution but i don't know if model class has many lists then how can i get the list in javascript.
<script type="text/javascript>
var obj=#Model;
</script>
i had tried the below method too. but it shows the name json is not exist in this current context
var obj = JSON.parse('#Html.Raw(Json.Encode(Model))');
please help me to solve this issue.
I just ran a test for you with the following code:
#model Project.ViewModels.TestViewModel
#using System.Web.Helpers
<script type="text/javascript">
var obj = JSON.parse('#Html.Raw(Json.Encode(Model))');
</script>
ViewModel:
public class TestViewModel
{
public string Test { get; set; }
}
It produces the following output:
<script type="text/javascript">
var obj = JSON.parse('{"Test":"Value123"}');
</script>

Grid.Mvc.Ajax extension grid initialization

Hi I'm very new to Web GUI dev using JQuery & Ajax and I'm trying to get the nuget package Grid.MVC.Ajax working. The readme states the following:
Follow thse steps to use Grid.Mvc.Ajax
1. Include ~/Scripts/gridmvc-ext.js after your ~/Scripts/grimvc.js include.
2. Include ~/Content/ladda-bootstrap/ladda-themeless.min.css CSS after your Bootstrap CSS/LESS include.
3. Include Ladda-bootstrap Javascript via the ~/Scripts/ladda-bootstrap/ladda.min.js
and ~/Scripts/ladda-bootstrap/spin.min.js.
4. Create a view model for you grid data, for example:
public Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
5. Add a Razor partial view for your grid data that uses an AjaxGrid<T> as the model type,
Where T is your view model type:
#using GridMvc.Html
#using GridMvc.Sorting
#model Grid.Mvc.Ajax.GridExtensions.AjaxGrid<Models.Person>
#Html.Grid(Model).Columns(columns =>
{
columns.Add(c => c.FirstName);
columns.Add(c => c.LastName);
}).Sortable(true).WithPaging(10)
6. Add a controller action to retrieve the data for the first page of data that includes the Ajax pager HTML:
public JsonResult Persons()
{
var vm = new List<Person>()
{
new Person() { FirstName = "John", LastName = "Doe" }
}
.AsQueryable();
var ajaxGridFactory = new Grid.Mvc.Ajax.GridExtensions.AjaxGridFactory();
var grid = ajaxGridFactory.CreateAjaxGrid(vm, 1, false);
}
7. Add a controller action to retrieve data for paged items that returns a JsonResult without the Ajax page HTML:
public JsonResult PersonsPaged(int page)
{
var vm = new List<Person>()
{
new Person() { FirstName = "John", LastName = "Doe" }
}
.AsQueryable();
var ajaxGridFactory = new Grid.Mvc.Ajax.GridExtensions.AjaxGridFactory();
var grid = ajaxGridFactory.CreateAjaxGrid(vm, page, true);
}
8. Call the ajaxify Grid.Mvc.Ajax JavaScript plug-in method setting the non-paged and paged controller actions and optionally a form
to apply additional filtering to the grid. All input and select elements in the given form will be passed into your paged and non-paged controller actions:
$(".grid-mvc").gridmvc().ajaxify({
getPagedData: '/Home/Persons',
getData : '/Home/PersonsPaged',
gridFilterForm: $("#gridFilters")
});
I have set things up as stated but I'm having problems in step 8. as I'm not sure how to call the JavaScript code in order to populate the grid. I have enclosed the above in a $(document).ready call but that doesn't seem to work :-( Any help would be much appreciated. Thanks
You have two options: loadPage and refreshFullPage
this will call your PersonsPaged method:
$(".grid-mvc")
.gridmvc()
.loadPage()
and this will call your Persons method.
$(".grid-mvc")
.gridmvc()
.refreshFullGrid()
also, in your Persons and PersonsPaged you can return a JSON like this:
public ActionResult Persons()
{
var vm = new List<Person>()
{
new Person() { FirstName = "John", LastName = "Doe" }
}.AsQueryable();
var ajaxGridFactory = new AjaxGridFactory();
var grid = ajaxGridFactory.CreateAjaxGrid(vm, 1, false);
return Json(new { Html = grid.ToJson("_YourPartialWithGridCode", this), grid.HasItems },JsonRequestBehavior.AllowGet);
}
I resolved the problem adding the URI.js file on the scripts tag before gridmvc.js and gridmvc-ext.js. When I installed Grid.Mvc.Ajax by Nuget, it added this file.
I called the code inside the $(document).ready(function() { ... }) and used twice ways.
1 - The javascript object of the grid using the grid's name.
2 - I did the same way that you did calling ajaxify method after gridmvc method using a jquery selector and it worked to me.
<script>
$(document).ready(function () {
$(".grid-mvc").gridmvc().ajaxify(
{
getPagedData: "/Product/Grid",
getData: "/Product/Index"
});
});
</script>
or
<script>
$(document).ready(function () {
pageGrids.productGrid.ajaxify(
{
getPagedData: "/Product/Grid",
getData: "/Product/Index"
});
});
</script>
"productGrid" is the grid's name. I hope to have helped.

Categories