How can I pass #Model to Angular ng-init - asp.net

Isn't it possible to pass #Model to ng-init in ASP.NET MVC 4 view? When I do it like data-ng-init=init(#Model) it is undefined in the init() function.
$scope.init = fuynction(model){
console.log(model); // prints undefined
}
By the way I'm new to AngularJs. Any help is appreciated in advance.

As I commented, you need to translate between your server-side objects (e.g. #Model) and client-side objects.
For example, if you just wanted to use the Name property of #Model you could do something like this:
<div ng-init="init('#Model.Name')"></div>
$scope.init = function(name){
console.log(name); // prints value of name
}
Notice, that even in this simple example, it is necessary to format #Model.Name into a JavaScript string (by putting quotes around it).
Probably, you don't want to use the entire #Model object. It is best to choose only the fields you want and pass them in individually.
If you need access to a lot of data from the server, it is recommended to use $http service and make a server call for the data.

Serialize you model into json string, using Newtonsoft.Json assembly or similar and pass the serialization result to data-ng-init.

inlcude the #using ProjectApp.Models then data-ng- init="init(#Newtonsoft.Json.JsonConvert.SerializeObject(Model))"

Related

Declaration of model in Razor View in mvc4 asp.net

I am new to asp.net mvc4 and there is something i don't understand well.
Why do I have to declare the Model using #model at top of the view, if I already pass an object to the View in the controller.
Taking an example :
Controller:
public ActionResult countryDetails(int id)
{
Country country = db.Country.Find(id);
return View(country);
}
View:
#model MvcApplication2.Models.Country
#{
ViewBag.Title = "countryDetails";
}
...
The controller returns a View with an object as parameter, so the model should be already known. I'm sorry if it is obvious, but I can't figure out why this is not a "double" declaration.
Thanks for you help !
The declaration at the top will do two things for you:
It will allow intellisence to know what type you are using when you type in #Model or use any of the Html helper extensions.
It will also check at runtime that model passed in can be cast to the type the view expects.
Its not necessarily a "double declaration" as it is analogous to specifying a type to a parameter on a method. Like so
Person Someone = new Person();
RenderView(Someone);
...
void RenderView(Person model) { }
By default your view inherits from System.Web.Mvc.WebViewPage<TModel>
You can optionally override this class, it's default ASP.NET inheritance mechanism:
#inherits System.Web.Mvc.WebViewPage<List<CompanyName.MyProduct.MyCategory>>
Or you can just simplify this since MVC3 like this:
#model List<CompanyName.MyProduct.MyCategory>
This sugar syntax was made to simplify code typing.
This declaration give you some things
View automatically cast object to the preferred type
You receive type-defined 'model' property which allows you to access
to your object methods and properties
Just believe that this is a method which accepts object and cast it to the specified type that you provide
The main reason is type-safety, it allows you to work with strongly typed views with the benefit of intellisense, compiler error hints, invalid casting etc.
Also, another reason is for readability - it acts as a reminder to what sort of model it is you are actually dealing with instead of having to keep referring back to the controller.

How to render editor template for model property by property name

The end goal is to render an editor template, for a model property, known only at run time, that will not take it's value from the ViewBag.
Html.Editor will use the ViewBag value if the property names match. I don't want this and I hate this "feature".
I hope that this is possible somehow:
var propName = "MyProperty";
var expression = GiveMeTheExpression();
#Html.EditorFor(expression,"MyEditorTemplate")
If not this then some way of rendering an editor template without the viewbag values being used instead of the model's values. I'm totally fine with doing this, IF I CAN IGNORE THE VIEWBAG VALUES SOMEHOW:
#Html.Editor(propName, other, arguments)
You'll probably have to use Html.Partial with a custom ViewDataDictionary.
object knownAtRuntime = ViewBag.ObjectName; // Adapt to your solution
string templateName = String.Concat("EditorTemplates/", knownAtRuntime.GetType().Name);
#Html.Partial(templateName, knownAtRuntime, new ViewDataDictionary(knownAtRuntime));
Note: I made this example simple to illustrate the core concept but you can of course extend it to read UIHintAttribute etc if you like.
Note 2: You may also want to copy values from Html.ViewData to the new ViewDataDictionary to keep your modelstate etc.
Why not try this ?
#Html.EditorFor(x=>x.SomePropertyName)
Assuming SomePropertyName is the name of a Property of your Model which is strongly typed to your view.
Shyju taking about strongly typed object, if I understand you correctly, you need something like: asp.net mvc 3 and dynamic view generation
My solution was to use the #Html.Editor() method with property name as string and to use ViewBag keys that are very unlikely to be found on the model object.
Not ideal, but should work well.

Why have a separate call to get Json?

I need to get some Json to the client side from the server and it's somewhat troublesome as almost all tutorials assume an Ajax call to a separate action to get the Json.
This led me to think that there must be some reason why it is done this way. In Asp.Net MVC we can pass a Model along with the view to get the information but we can't seem to easily pass a Json object. Instead you are supposed to make a separate call to get this information.
What if the Json info is known when the page is generated, why not generate it at the same time?
I'm sorry if I wasn't clear enough. While it's nice to hear of ways to get Json to the client, the question is actually whether there is a specific reason the Ajax call method is much more popular, like security or anything like that.
Can you put something like this into your view? (rough pseudo code, assuming using a Razor view)
< script >
var myJSON = { Field: #model.Field, Field2: #model.Field2 };
< /script >
Because you do not need both at the same time... on the first call will be to get html (the view of the data - represented by a view model), and any ajax calls will be to get the possibly updated data (json serialized view model).
No reason why you can't. You could use the javacript serializer to create a JSON string that drop on the page. You could also create an action that return the json string that you called from a script tag.
What you want if you're using KnockOut, would be the Mapping plugin that turns an ordinary JS object, like that generated above, into an observable ready for KnockOut to use. See here from info. http://knockoutjs.com/documentation/plugins-mapping.html
You can use content-negotiation by setting accept header. This is considered a best practice (and according to some RESTful).
This needs to be supported and implemented at server as well. ASP NET MVC does not make it easy to support content-negotiation and you have to implement it yourself by if-else or using ActionFilter and implementing action selector.

JsonResult or Json: which to use?

In ASP.NET MVC 3, which is more correct to use: Json() or new JsonResult()? Either returns the same result. Thanks for helping solve an office debate.
Json() is just an extension method that actually returns a JsonResult object behind the scenes (rather than needing to call the constructor directly).
I almost always use the Extension Method myself. This keeps more in line with the other common return types from Action Methods like View(), PartialView(), etc.
I also make sure to create an extension method for any custom ActionResult types that I create. In the end it's a matter of personal preference.
If you a returning a large dataset as a data source for grid or other UI controls via Ajax, sometimes if this dataset is over 1000 records UI controls will not bind because of maximum Json length is not specified.
So instead of
return Json(data),
you can do this: return new JsonResult(Data = data, MaxJsonLength = 50000);

Passing a list of object from a view to the controller in asp.net mvc?

Is this possible?
What I want to do is pass a list of objects as a paramter in an actionlink
At the moment when I try to do this the list is always empty by the time it reaches the controller!
In the view
<%= Url.Action("ActionName", new { list = Model.ListOfObjects}) %>
In the controller
public ActionResult ActionName(List<Object> list)
{
//Do stuff
}
In terms of whether or not it's possible - it's possible, but not in the way you're trying. Keep in mind that this will translate to a URL which will get parsed by MVC and the different parameters will get passed to the action either as direct parameters or through a model binder.
I would recommend that you try to figure out what the URL will have to look like and then maybe do some custom code to generate the URL (maybe use a custom helper function/extension method). If you combine this with a custom model binder you should have a pretty elegant solution which does exactly what you want.
For example, if your list has 3 objects of type string you could write a helper to generate a url like this (let's say the list contains 'first', 'second', and 'third')
/Controller/Action?obj1=first&obj2=second&obj3=third
Now you simply need to write a model binder that looks for entries called 'obj1','obj2', etc and simply add the results into a list.
While it may take the list of objects, it probably won't render what you are expecting to see; it may actually suck in the values of the list class (or whatever class this list represents) and use that as the params.
Not through a get request, unless you write out the params manually and deserialize the params too. Or, instead, do a postback to the server with these values within the form; then, this would populate correctly.
HTH.
Something like this would work, I suggest making a helper to contain this logic if you need it in a lot of places.
<% var values = new RouteValueDictionary();
for (int i = 0; i < Model.ListOfObjects.Count -1; i++)
{
values.Add("list["+i+"]", Model.ListOfObjects[i]);
}%>
<%= Url.Action("ActionName", values); %>
The action will know how to handle the list in the controller.

Resources