I am starting to learn asp.net MVC and probably it's a silly question, but I can't seem to figure out what I am doing wrong.
I have a controller that returns data, between which some variables stored in ViewBag. With the variables stored in the ViewBag, I create a table (they store the number of rows and columns).
[HttpGet]
public ActionResult Index()
{
ViewBag.widht = someNumber1;
ViewBag.height = someNumber2;
return View(someData);
}
[HttpPost]
public ActionResult Index(int someNuber)
{
//calculate the new width and height using someNumber
ViewBag.widht = newWidth;
ViewBag.height = newHeight;
return PartialView();
}
The View has a button, and when the user clicks on it I want to recreate the table with different dimensions.
function OnClick_prev() {
#Html.ActionLink("Index", "Index", new {id = ViewBag.width+5})
}
The problem I have, is that the body of the JavaScript function throws an error (seen in firebug), not really sure why. The error is SyntaxError: syntax error < a href="/Home/Index/36">Index
Any tips?
Change your JS like below
function OnClick_prev() {
var loc = '#Url.Action("Index", "Index", new {id = (int)ViewBag.width+5})';
window.location = loc;
}
The problem is the underlying type of ViewBag is ExpandoObject, ExpandoObject is effectively Dictionary<string, object>, therefore ViewBag.width+5 is the equivalent to
object + int
which won't compile. You will need to cast your width property to int before you perform the calculation
{ id = ((int)ViewBag.width + 5) }
EDIT: just realised my initial answer wouldnt work because you are using POST.
change your GET method to this
[HttpGet]
public ActionResult Index(int id)
{
// Do some check on id to see if it has a value then add your old POST code here
ViewBag.widht = someNumber1;
ViewBag.height = someNumber2;
return View(someData);
}
MVC has default route of
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
so you dont have to pass an id to the method as its optional
then in your view change your code to
#Html.ActionLink("Index", "Index", new {id= (int)ViewBag.width+5})
Related
Within my view i have a piece of JavaScript where i have declared a variable ' Fk '
<script>
function test(clickedID)
{
var Fk = clickedID;
}
</script>
I want to be able to use 'Fk' within an action result by passing it as a parameter.
For example:
[HttpPost]
public ActionResult ReadFk(int Fk) //i would imagine id pass Fk to the ActionResult through the use of its paramaters..?
{
var dataFileFk = Server.MapPath("~/App_Data/ForeignKeyValue.txt");
var textFileDataFk = Fk + Environment.NewLine;
System.IO.File.WriteAllText(dataFileFk, textFileDataFk);
return View();
}
Is there an easy way of doing this?
Thank you!
EDIT:
Since you want to pass a variable from javascript to a controller action and you want to be redirected afterwards, you can use window.location.replace(url)
<script>
function test(clickedID)
{
var Fk = clickedID;
// this will redirect you to a controller action while sending data parameter
window.location.replace("http://yoursite.com/ControllerName/WriteFK?data="+Fk);
}
</script>
Then create an action that will receive the data and write that to the text file;
// remove HttpPost and change to ActionResult
public ActionResult WriteFK(string data)
{
// variable data will contain the FK
// write to text file here
// return view
return View();
}
Is it possible to return 2 separate views to an ajax call in Asp.net?
for example, if foo1 and foo2 are 2 ActionResult methods each returning a view?
return Json(new { a = foo1(), b = foo2() });
currently attempting this, the end result is that javascript gets it back as a class object rather then the actual view, anybody know how to get the resulting rendered html instead?
EDIT: I guess what I'm actually going for, is there a way for me to return the rendered view in string format?
Yes their is a way of returning view in string format.
For this you need to do following things:
1.You need some method in which you can pass your viewname along with object model. For this please refer below code and add to your helper class.
public static class RenderViewLib
{
public static string RenderPartialView(this Controller controller, string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = controller.ControllerContext.RouteData.GetRequiredString("action");
controller.ViewData.Model = model;
using (var sw = new StringWriter())
{
ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
viewResult.View.Render(viewContext, sw);
return sw.GetStringBuilder().ToString();
}
}
}
The above code will return your view in string format.
2.Now call above method from your json call like this:
[HttpPost]
public JsonResult GetData()
{
Mymodel model = new Mymodel();
JsonResult jr = null;
jr = Json(new
{
ViewHtml = this.RenderPartialView("_ViewName", model),
ViewHtml2 = this.RenderPartialView("_ViewName2", model),
IsSuccess = true
}, JsonRequestBehavior.AllowGet);
return jr;
}
and you will get your view as string format from your json call.
Hope this is what you are looking for.
I have this modelView
public class Ue
{ public class uEkranModel
{
public List<Grup> Grup = new List<Grup>();
private List<Secim> _secim;
public List<Secim> secim
{
get
{
if (_secim == null)
_secim = new List<Secim>();
return _secim;
}
set { _secim = value; }
}
}
public class Secim
{
public Guid uGuid { get; set; }
public Guid fGuid { get; set; }
}
}
I need to fell the List secims items with JS and post it back to controller.
I have tried to :
1)initialize the list in the controller :
Controller :
gidecek.Data = new Models.Ucak.UcakDeneme.uEkranModel();
gidecek.Data.secim.Add(new Models.Ue.Secim { uGuid = new Guid() });
gidecek.Data.secim.Add(new Models.Ue.Secim { uGuid = new Guid() });
View :
#using (Html.BeginForm("deneme", "U", FormMethod.Post, new { id = "secimTamam", style = "display:none" }))
{
#Html.EditorFor(m => m.Data.secim[0])
#Html.TextBoxFor(m => m.Data.secim[0].uGuid, new {id="gidis" })
}
JS :
$("#Data_secim_0__ucusGuid").attr("value", index);
This way , when the code is executed the value field of the textboxfor is changed(when the JS fired) but when I check the post data in controller , it is NULL.
also tried :
$("#Data_secim_0__ucusGuid").val(index);
which doesnt cahnge the value of teh textbox.
What I need is to fill the model values with js and post the form with js as well.(The data user is selecting is different, I am just posting back the GUID of the items within a form.)
2 possible issues. Your getter is initializing a new List<Secim>. Try initializing it in the constructor
public class uEkranModel
{
public uEkranModel()
{
secim = new List<Secim>();
}
public List<Secim> secim { get; set;}
....
}
Also I have seen other posts on SO indicating problems posting back GUID's (and one solution that was accepted was to use a view model with the GUID's converted to strings)
I want to use my ViewBag in JavaScript array. I follow using viewbag with jquery asp.net mvc 3, and I think the following code is what I am looking for,
#model MyViewModel
<script type="text/javascript">
var model = #Html.Raw(Json.Encode(Model));
// at this stage model is a javascript variable containing
// your server side view model so you could manipulate it as you wish
if(model.IsLocal)
{
alert("hello " + model.FirstName);
}
</script>
But this code causes error for Json.Encode, then I add System.Runtime.Serialization.Json, but It also cause error for Encode, says no method for Encode, I already include Newtonsoft.Json, but still no result.
My ViewBag data ::
public ActionResult Dashboard()
{
ViewBag.inc = (from inc in db.Incident select inc.Title).ToList();
return View();
}
And I want to use this ViewBag.inc data in JavaScript array
As you said, you are already referencing the Newtonsoft Json.Net library, you can use this following code::
var inc = '#Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(ViewBag.inc))';
inc= JSON.parse(inc);
$.each(inc, function(index, data) {
//you next code
});
The snippet you are using does not use the ViewBag, but the Model. Regardless, if you want to print the serialisation of an object to the view, and you are already referencing the Newtonsoft Json.Net library (as you said you are), then you can do the following:
var model = #Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model));
If you want to use the item in the ViewBag instead, you can do:
var model = #Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(ViewBag.inc));
You can use like for ViewBag -
var mn = #{#Html.Raw(Json.Encode(ViewBag.ViewBagProperty));}
alert(mn.YourModelProperty);
And for Model -
var mn = #{#Html.Raw(Json.Encode(Model));}
alert(mn.YourModelProperty);
There is no need for NewtonSoft.Json, we can use default System.Web.Helpers.Json.
Update: Here goes the complete solution with Model, the same concept can be used with ViewBag too -
Lets say you have this Model -
public class XhrViewModel
{
public string data1 { get; set; }
public string data2 { get; set; }
}
Then in the controller action you are constructing the List of above Model in following way -
public ActionResult GetData()
{
List<XhrViewModel> model = new List<XhrViewModel>();
model.Add(new XhrViewModel() { data1 = "Rami", data2 = "Ramilu" });
return View(model);
}
Then on the View, you can have something like this -
#model IEnumerable<Rami.Vemula.Dev.Mvc.Controllers.XhrViewModel>
#{
ViewBag.Title = "GetData";
}
<h2>GetData</h2>
<script type="text/javascript">
var mn = #{#Html.Raw(Json.Encode(Model));}
alert(mn[0].data1);
</script>
And when you execute the page -
that's my function:
<script> function Calculate()
{
var ItemPrice = document.getElementById("price");
var weight = document.getElementById("weight");
var SelWeight = weight.options[weight.selectedIndex].value;
alert(SelWeight);
var Category = document.getElementById("SelectedCategory");
var SelCategory = Category.options[Category.selectedIndex].value;
alert(SelCategory);
}
</script>
i want to get SelCategories.Tax and SelCategories.Duty to add them to weight value and total price to show the total in a label.. I'm using ASP.NET MVC 4 and this is my Model that i want to use
public class CategoriesModel
{
public int CategoryID { get; set; }
public string CategoryName { get; set; }
public decimal Duty { get; set; }
public decimal Tax { get; set; }
public IEnumerable<SelectListItem> CategoriesList { get; set; }
}
I think the best approach here is to use Json and something like Vue.js, Knockout.js, etc. (but also you can do it without these libraries, if your case is simple).
First, you need to install Json support with a command in PM console:
PM> install-package NewtonSoft.Json
Then, in your view you can convert your model to javascript object like this:
#model ...
#using Newtonsoft.Json
...
<script type="text/javascript">
var data = #Html.Raw(JsonConvert.SerializeObject(this.Model));
</script>
Then you can access all the properties in your model with in plain JavaScript:
var id = data.CategoryID;
That's it! Use knockout (update 2018: this is obsolete, there is no reason you should use knockout now) if your logic is complicated and you want to make your view more powerful. It could be a little bit confusing for newbie, but when you get it, you'll gain the super-powerful knowledge and will be able to simplify your view code significantly.
You need to create actions (methods in the controller) that return JsonResult.
From the client side, make ajax calls to the server to recover and use that data. The easiest way to do this is to use any of the jQuery ajax methods.
public JsonResult GetData(int id)
{
// This returned data is a sample. You should get it using some logic
// This can be an object or an anonymous object like this:
var returnedData = new
{
id,
age = 23,
name = "John Smith"
};
return Json(returnedData, JsonRequestBehavior.AllowGet);
}
When you use a jQuery get to the /ControllerName/GetData/id, you'll get a JavaScript object in the success callback that can be used in the browser. This JavaScript object will have exactly the same properties that you defined in the server side.
For example:
function getAjaxData(id) {
var data = { id: id };
$.get('/Extras/GetData/1', // url
data, // parameters for action
function (response) { // success callback
// response has the same properties as the server returnedObject
alert(JSON.stringify(response));
},
'json' // dataType
);
}
Of course, in the success callback, instead of making an alert, just use the response object, for example
if (response.age < 18) { ... };
Note that the age property defined in the server can be used in the JavaScript response.
If you prefer a class try jsmodel. After converting the mvc view model to javascript it adds the benefit of retrieving DOM updates.
var jsmodel = new JSModel(#Html.Raw(Json.Encode(Model)));
Then anytime you want to get the latest state of the DOM do this to update your variable:
var model = jsmodel.refresh();
Website:
http://chadkuehn.com/jquery-viewmodel-object-with-current-values/
There is also a nuget:
https://www.nuget.org/packages/jsmodel/
var errors = '#Html.Raw(Json.Encode(ViewData.ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage)))';
var errorMessage=JSON.parse(errors);