When I return a JSon value, i simply want to put a string inside an existing div
EDIT: Let me Rephrase this: I want my MVC controller to return a JSON object to the UpdateTarget specified in the MVC AJAX call. Instead of returning "content".
Assume your JSON String looks like this:
var jobj = '{"name":"value"}';
and you have a div on the HTML with id mycontentdiv then
document.getElementById("mycontentdiv").innerHTML = jobj.name;
will take the "value" and place it in the div.
Without further details it is difficult to be more specific.
Related
I have a project where I am passing the data from C# to cshtml by something like this:
public IActionResult Index()
{
ViewData["temp"] = "abc"
return View();
}
This value is then received in the cshtml file where I can read this as
var temp = ViewData["temp"];
I have a typescript file that is then booted from this cshtml file.
My question is, how can I use this temp variable in my typescript code. I don't want to create a 'div' element for this temp data and then read its value in typescript as this will not be a clean thing to do from security perspective.
Can you please suggest some way to do it in a proper way?
In your view returned by the Index action just choose an existing element (you can choose the body element if your view contain it) and in that element add an data-* attribute (you can name it data-temp) like below :
<SomeElementInMyView data-temp="#temp">...</SomeElementInMyView>
In your Typescript file, I suppose you're using jQuery so get the data value like this:
let dataTemp = $("SomeElementInMyView").data("temp");
You can pass it as string variable in html eg.
let typeScriptVariable: string = "#temp";
I have a template editor, Currency.cshtml like this:
#model decimal?
...
string value =
// Some calculations that returns value formatted as currency
Currency: #value<br/>
#Html.TextBox("", value, attributes)
I have a view which uses this template like this:
#Html.EditorFor(m => m.Amount.Value, "Currency", someAdditionalViewData)
When this view is rendered as a partial directly inside another view, the result is as expected: both the text, and the editor show the formatted variable "value", like so:
Currency: 1.223,18 <== well formatted
[ 1.223,18] <== this is the input type=text, well formatted
However, if I get the view using Ajax (Ajax.ActionLink), I get the firs part formatted, but the second one unformatted, like so:
Currency: 1.223,18 <== well formatted
[ 1223.18] <== this is the input type=text, not formatted!!
Any idea why this can be going on? Should I change the final #Html.TextBox("", value, attributes) in my template for something else?
I don't know the reason, but after investigating for some time, I can assure that the final call to #Html.TextBox("", value, attributes), on an Ajax request behaves in a different way than on a PartialView render.
In a PartialView render, it creates the desired input element, with the provided formatted value. However, in an ajax request, it looks up for info on the model and creates its own version of the textbox, including the unobstrusive validation attributes and so on.
The only way to solve this problem is not to use the TextBox method, but create an input writing it directly with a TagBuilder. Pay attention to the way of getting the Id and name for the input element.
#{
string value = ... // Format as desired
// Create the required attributes
// NOTE: HtmlAttributes is simply a custom "fluent" attribute builder,
// inherited from IDictionay<string,object>
var attributes = HtmlAttributes.Empty
.Add("type", "text")
.Add("value", value) // formatted value
.Add("id", ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(""))
.Add("name", ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(""))
.AddStyle("text-align", "right");
// You can add extra attributes, i.e. unobtrusive validation, provided by user...
var extraAttibutes = ...
attributes.Merge(extraAttributes);
// Use the tag builder to create the input
TagBuilder tb = new TagBuilder("input");
foreach (var attribute in attributes)
{
tb.Attributes.Add(attribute.Key, attribute.Value.ToString());
}
var textBox = tb.ToString(TagRenderMode.SelfClosing);
// Then, either write it directly to the writer...
ViewContext.Writer.Write(textBox);
}
#* ...or use Html.Raw *#
#Html.Raw(textBox)
Of course, there are a lot of details omitted (how to get unobtrusive or any other extra attributes for the tag and so on). The best soultion would be to discover why the behavior changes from a "complete" render and an ajax request render. All the View metadata looks exactly the same, but works in a different way.
I also had a partialview that used an editortemplate which worked when initially loading the page. However when using ajax to call for the partial the editortemplate wasn't used.
For me turned out I had to move it to a different folder:
From
Views/[Controllername]/EditorTemplates
To
Views/Shared/EditorTemplates
I have an MVC WebApi app. I'm trying to do something basic - pass a string via JSON in the body. My client submits a small number of key/value parameters, and when the MVC router gets them, it begins to interpret the content of the strings.
An example JSON body is
{ "myKey":"red,yellow,brown,orange","foo":"bar" }
My MVC controller method is
public Dictionary<string, string> PostMyAction([FromBody] str1, [FromBody] str2) { }
I would expect str1 == "red,yellow,brown,orange" but instead I get "Can't bind multiple parameters ('str1') to the request's content."
Why is it parsing the first string as a list of parameters?
Shouldn't your Controller method be an ActionResult?
You do can receive more than one parameter on your actions, but for a clear code, I recomend use one ViewModel that contains properties that will represent your View, and Binded on submit.
I have a view that inherit the following:-
#model MvcApplication.Models.Application
But i need to know if it is possible to pass JSON objects to my view in the same way i am passing the model objects?
Since i have the following Controller:-
public ActionResult ListPackages()
{
using (var client = new WebClient())
{
var query = HttpUtility.ParseQueryString(string.Empty);
//code goes here ....
return Content(json, "application/json");
}
}
which returns JSON using a API call, and then i am displaying the JSON on the view using JavaScript as follow:
$.ajax({
url: $('#geturl').data('url'),
type: 'GET',
cache: false,
success: function (result) {
$.each(result.data, function (key, val) {
var str = val.packageName;
$('<li/>', { text: str })
.appendTo($('#products'));
});
}
The problem with displaying the JSON using JavaScript is that it will make too difficult for me to work easily with the JSON objects, such as creating links based on the returned JSON or creating table that contain the JSON. So my question is: Is it possible to pass a JSON object instead of a Model object from my controller to my view?
Server- vs client-side confusion
You're talking two things here:
Creating a view: controller passes model to the view on the server side and it doesn't make much sense to do so using JSON, because an in-memory object is being passed to view engine.
Consuming JSON data on the client: what you're talking about here is client-server Ajax communication where you request data from the client and get JSON returned from the server. This has arguably nothing to do with model data being passed to the view
Best solution using JSON
In order to easily consume JSON data (in your case it's an array of packages) on the client to generate resulting populated HTML is to use some sort of templating on the client side. jQuery used to have non-final templating plugin which is now a separate project. I've had great experience with it but there are other plugins as well. Use the one that you feel most comfortable with its syntax.
Where to put those templates?
If you know the structure of your JSON objects passed from the server at the point of creating your view, you can put templates in the view itself and they'll just wait untill being used on the client.
If you don't know the structure of your JSON objects then you'll have to pass templates either along JSON object or as a separate request.
The first approach is the usual one, the second one is rarely used and is much more dynamic.
Best solution not using JSON
If you don't like parsing JSON to HTML results (either manually or using templates), you can always make Ajax requests to your controller action, which would return a prepared HTML as a partial view instead of JSON result. This way, you could easily just put that HTML onto your page without any JSON data manipulation.
What do you gain here? Well suppose you have this functionality in your app:
You have a view that displays a paged list of packages.
When user first accesses the page first page of packages are being returned
Paging to next page is done via Ajax and the list is being replaced by returned data
If you'd create a partial view for your subsequent Ajax request, you can use the same partial view in your main view to display the first page of packages. This will ensure that you only have to change one partial view and display would change on inital page load as well as subsequent package paging.
If you used view + JSON + templating that means that you have to maintain two presentations of package list: the one being used in the view for the first page and the template that displays subsequent paging.
Which one then?
All things being equal it makes the second solution better. But the choice of course depends on your case (of things not being equal) and you should be able to determine which one is best in your scenario.
No, you can't. A view must be strongly typed to a model. So one solution would be to deserialize this JSON into a model object before passing it to the view:
public ActionResult ListPackages()
{
using (var client = new WebClient())
{
var query = HttpUtility.ParseQueryString(string.Empty);
//code goes here ....
var model = new JavaScriptSerializer().Deserialize<MyViewModel>(json);
return View(model);
}
}
where MyViewModel would of course reflect the JSON structure that you are working with.
Let's say I have a partial view X.ascx like this:
<div id = "updateTargetIdForAjaxForm">
... javascript code which only has function definitions.
... ajax form with buttons inside
<div id = "stuff"></div>
<script type = "text/javascript">
do things to "stuff" div as soon as X.ascx is loaded.
</script>
</div>
Now I want to update things on X.ascx, based on Ajax response. Earlier, I was returning PartialView but inline javascript that does things to stuff div wouldn't like that, meaning the inline javascript just won't get executed when X.ascx is reloaded.
So is there a way I can not return PartialView in my controller, but just update ViewData values and tell the PartialView to re-grab the updated ViewData values? And also call one or two javascript functions based on the response from server maybe?
I see two possible ways to go:
Fixing your javascript code to run with dynamically loaded partial view:
http://api.jquery.com/live/
http://api.jquery.com/delegate/
These two should help you out.
The other way is to create an action on your controller that would return JSON result and from jQuery you should be able to handle JSON object and update your form. Your Action could look like :
public JsonResult GetFormValues()
{
var jsonFormValues = new
{
key1 = "abc",
key2 = "123",
key3 = "abcdef"
};
return Json(jsonFormValues, JsonRequestBehavior.AllowGet);
}
and check out http://api.jquery.com/jQuery.getJSON/ on how to handle the result