How to pass parameters from class to angular $scope - angularjs

if i have this class:
public class MainMenuModel
{
public MainMenuModel(string transKey, string stateName, string displayUrl, bool hasSubMenu= false,List<SubMenuModel>subMenu=null)
{
TransKey = transKey;
StateName = stateName;
DisplayUrl = displayUrl;
HasSubMenu = hasSubMenu;
SubMenu = subMenu;
}
public string TransKey { get; set; }
public string StateName { get; set; }
public string DisplayUrl { get; set; }
public bool HasSubMenu { get; set; }
public List<SubMenuModel>SubMenu { get; set; }
}
And if i populate that class like this:
MainMenu.Add(new MainMenuModel("MY_TICKETS", "account.tickets", "/account/tickets/"));
MainMenu.Add(new MainMenuModel("TRANSACTION_HISTORY", "account.transactionhistory", "/account/transactions"));
MainMenu.Add(new MainMenuModel("PAYIN","account.payin","/account/payin"));
MainMenu.Add(new MainMenuModel("PAYOUT", "account.payout", "/account/payout"));
MainMenu.Add(new MainMenuModel("TICKET_PAYOUT", "account.ticketpayout", "/account/ticketpayout"));
MainMenu.Add(new MainMenuModel("SETTINGS","default","default",true,
new List<SubMenuModel>(){
new SubMenuModel("PERSONAL_INFORMATION","account.personalinformation","/account/personalinformation"),
new SubMenuModel("NOTIFICATIONS","account.notificationsettings","/account/notifications"),
new SubMenuModel("CHANGE_PASSWORD","account.changepassword","/account/passwordchange"),
new SubMenuModel("GAME_SETTINGS","default","default"),
}));
MainMenu.Add(new MainMenuModel("PROMOTIONS", "default", "default", true,
new List<SubMenuModel>(){
new SubMenuModel("BONUSES","default","default"),
new SubMenuModel("COMPETITIONS","default","default"),
new SubMenuModel("VOUCHER_REDEEM","default","default"),
}));
How can i call this in angular ..and pass it to $scope.something?Any suggestion?

If you need forming page on server - try to serialize this collection and put in on angular controller init
<div ng-controller="SomeController" ng-init="initialize('#Model.ToJson()')">

My recommendation is that you setup WebApi along with your existing ASP.NET MVC layer.
With that being said all you need to do is to implement the Rest services as GETs or POSTs and from your angular a simple invoke with $http :
Server Side
Using Microsoft Web Api Controller class "ValuesController" but it can be any class name which looks like this:
public class ValuesController : ApiController
{
public string Get(int id){ return "value"; }
...
Client Side
In my AngularJS Controller function it gets the value using $http service:
$http({method:'GET',url: '/api/values/1'}).success(function(data){
$scope.value =data;
})

First, you'll need to setup a server endpoint you can reach through ajax, that'll return the MainMenu structure as a JSON response.
Once you have that endpoint setup, there are several ways to get this data into angular, although I think the best way is to create an Angular service to manage this data. Something like this (bear with me, since I don't know the particulars of your project):
angular.module('application').factory('mainMenuService', ['$http', function($http) {
var ServiceInstance = {
_menuItems: [],
_fetchMenuItems: function() {
var self = this;
$http.post('your/server/endpoint').success(function(data, status, headers, config) {
// Clear exisiting items
self._menuItems.length = 0;
// Assuming menu items have been returned as JSON structure
// Add them all into the Service's mainMenu cache
self._menuItems.push.apply( self._menuItems, data.menuItems );
});
},
getMenuItems: function() {
if (!this._menuItems.length) {
this._fetchMenuItems();
}
// No need to wait on async operation because we're using the same array instance,
// and angular will observe this instance and detect when new items are added.
return this._menuItems;
}
};
return ServiceInstance;
}]);
Then, in your Angular controllers use the service:
// Notice how we reference the 'mainMenuService' here, and angular will inject it automatically
angular.module('application').controller('mainMenuController', ['mainMenuService', function (mainMenuService) {
$scope.mainMenuItems = mainMenuSevice.getMenuItems();
}]);
That way you'll decouple the data from the controller, and you can reuse the service in any controller where it's needed.

Related

JSON object not passing as param to webApi PUT method

I’m using Angularjs and asp.net mvc 5 with webApi2.
I’m having some trouble calling a custom PUT method. I’ve done some studying for the past few days, and although I have a decent feel for the situation, I can’t get my JSON object to pass as a parameter for some reason.
Route template:
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
Web api controller and model (shortened for brevity):
public class AttModel
{
public string dc { get; set; }
public string dt { get; set; }
}
[HttpPut]
public IHttpActionResult PutAttendRecord([FromBody]AttModel model)
{
string dc = model.dc;
DateTime dt = Convert.ToDateTime(model.dt);
var record = (from tbl in db.attend_am_y1
where tbl.dc_number == dc && tbl.class_date_am == dt
select tbl).SingleOrDefault();
record.status_am = "z";
db.SaveChanges();
}
Javascript object (angularjs PUT):
$scope.updateRecord = function () {
var stuInfo = {
dc: $scope.student.dc,
dt: $scope.student.dt
};
$http.put("/api/attendance/PutAttendRecord/" + stuInfo)
.then(function (d) {
alert(d.data.dc_number);
});
}
I tried using Newtonsoft without the extra AttModel class, and passing the param as jObject, but I still get a null value exception within the iHttpActionResult method. The data just isn’t making it to my method. Routing issue?
If I manually place values within these variables in the iHttpActionResult, the method works fine.
Assuming you are getting into your call alright,
you want to attach your object in the body
$http.put("/api/attendance/PutAttendRecord/", stuInfo)
.then(function (d) {
alert(d.data.dc_number);
});
and I don't think you need [FromBody] as I believe this is only specified if the function finds it unclear.

ASP.Net Web Api, POST multiple objects

I have this AngularJS Http Call
$http({
method: "POST",
url: Helper.ApiUrl() + '/Api/Case/SendCase',
data: { obecttype1, obj2, obj3},
}).then(function mySuccess(response) {});
Ant this ASP.net Web Api method
[HttpPost]
[Route("Api/Path/SendCase")]
public int SendCase(object application)
{
string applicantName = ((Newtonsoft.Json.Linq.JObject)application)["applicant"].ToString();
obecttype1 obj = JsonConvert.DeserializeObject<obecttype1>(((Newtonsoft.Json.Linq.JObject)application)["obecttype1"].ToString());
.........................
return ID;
}
This works pretty well, but I feel it is a bit dirty because I am parsing my objects in my method, so my question is
Is the are way to send multiple objects as params in a POST method, I would prefer to avoid modifying my model, avoid creating a class for this
So my Api Method would look like this
public int SendCase(class1 obecttype1, class2 obj2, class3 obj3)
"Is the are way to send multiple objects as params in a POST method, I would prefer to avoid modifying my model, avoid creating a class for this"
By design HTTP Post can only have one body and web api will try to cast the body to the parameter defined in the method signature. So sending multiple objects in the body and trying to match these against multiple params in the method signature will not work. For that you need to define a class which holds the other classes and match the body signature.
public class postDTO
{
public class1 class1Data { get; set; }
public class2 class2Data { get; set; }
public class3 class3Data { get; set; }
}
//The api signature
public int SendCase(postDTO application)
If you still don't want to add the new class then I would use the JObject directly as the parameter as this
[HttpPost]
public int SendCase(JObject jsonData)
{
dynamic json = jsonData;
JObject class1DataJson = json.class1Data;
JObject class2DataJson = json.class2Data;
JObject class3DataJson = json.class3Data;
var class1Data = class1DataJson.ToObject<class1>();
var class2Data = class2DataJson.ToObject<class2>();
var class3Data = class3DataJson.ToObject<class3>();
}
1. Define models for the parameters
public class ClassType1
{
public int Num1 { get; set; }
public string Str1 { get; set; }
}
public class ClassType2
{
public double Test2 { get; set; }
}
2. Use the models as the parameters on the API controller method
// Sorry this example is setup on .Net Core 2.0 but I think the previous
// versions of Web Api would have similar/same behavior
[Route("api/[controller]")]
public class ValuesController : Controller
{
[HttpPost]
public void Post(ClassType1 ct1, ClassType2 ct2)
{}
}
3. When posting, your objects inside the data {} have to have the keys that match the parameter name you defined on the Controller method
jQuery ajax
$.ajax({
method: 'post',
url: 'http://localhost:53101/api/values',
dataType: 'json',
data: {
// It takes key value pairs
ct1: {
num1: 1,
str1: 'some random string'
},
ct2: {
test2: 0.34
}
}
});
To summarize, yes you can post multiple objects back to the server, as long as
You define a key for each object and the key has to match the parameter name you define on the server method.
The object structure has to match.
-- update --
Just as a proof, here is the screenshot:
We have an app that uses DefaultHttpBatchHandler to accept multi-part POST requests. I believe it to be a bit clunky for many reasons but it is the built-in way to accept multiple objects on a single request in a structured fashion.
https://msdn.microsoft.com/en-us/library/system.web.http.batch.defaulthttpbatchhandler(v=vs.118).aspx
As for the script to create something, that I don't know about. Our callers that use this API are C# services that can create the multi-part requests using a simple client library we provide to help them do just that.

How to call custom name funtion

I am trying to figure, how to call a specific function name in WepApi.
Currently if i call the WebApi with that structure api/{controllerName
its working (in case that the function name start with "get")
What i am trying to accomplish is that:
in JS
$http.get("http://localhost:34662/api/webapi/CustomfunctionName/")
.then(function (response) {
vm.employees = response.data;
}
in WebApi
[HttpGet]
[Route(Name = "CustomfunctionName")]
public IEnumerable<tblEmployees> CustomfunctionName()
{
using (Entities entities = new Entities())
{
return entities.tblEmployees.ToList();
}
}
I also tried to add a decorator above the function in the WebApi:
[Route(Name = "CustomfunctionName")]
but it didn't help.
How can it be done?
Could you add RoutePrefix attribute at the controller, and try again?
[RoutePrefix("api/webapi")]
public class WebApiController : ApiController
{
[HttpGet]
[Route("CustomfunctionName")]
public IEnumerable<tblEmployees> CustomfunctionName()
{
}
}
Solution per #E.Meir: If you use [ActionName(...)], you should decorate it to every action method inside the controller.

Passing complex object from angular service to MVC controller

I am trying to pass complex object from angular service to MVC controller. Below is the code-:
Angular Controller
$scope.saveData = function () {
var resultData = new Object();
resultData.Name = $scope.Name;
resultData.Address = new Object();
resultData.Address = $scope.Address;
resultData.Address.Contact = $scope.Address.Contact;
var promiseOrganization = AngularService.saveResult(resultData);
promiseOrganization.then(function (result)
{
alert("Saved successfully.");
}
)
}
Angular Service
this.saveResult = function (resultData) {
return $http.post("/Form/SaveData/" + resultData);
}
MVC Controller
[System.Web.Http.HttpPost]
public string SaveData([FromBody] resultData data)
{
//operation to perform
return "Data Reached";
}
When I try passing complex object from Angular service to mvc controller. It gives me null i.e. object becomes null.
Please suggest.
When using the $http.post method you need to pass the data object as the second paramenter. You can read up on it here
So your angular code should look like
$http.post("/Form/SaveData/", data);
You then need a server side representation of the data you are passing the WebApi controller
public class MyCustomObject
{
public string Name { get; set; }
public MyCustomAddress Address { get; set; }
}
public class MyCustomAddress
{
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string Contact { get; set; }
}
You need to update your WebApi controller code to use the new server side class as the parameter. Note that I am not using the [FromBody] attribute as this link explains you only need to use the [FromBody] attribute when you want to force Web API to read a simple type from the request body(your type is a complex type)
To force Web API to read a simple type from the request body, add the [FromBody] attribute to the parameter
Updated WebApi Controller code without the [FromBody] attribute:
[System.Web.Http.HttpPost]
public string SaveData(MyCustomObject data)
{
//operation to perform
return "Data Reached";
}
Change your post function to something like this,
$http.post('/Form/SaveData/', resultData)
.success(function (data, status, headers, config) {
})
.error(function (data, status, headers, config) {
});
You are wrong in your post command. It should be:
$http.post("/Form/SaveData/",{resultData: resultData});
The problem is you need to add the following header -> 'Content-Type': 'application/x-www-form-urlencoded'
$http.post('/Form/SaveData/', resultData, {headers: {'Content-Type': 'application/x-www-form-urlencoded'}});

What is the best way to retrieve data using Web API 2 and AngularJS

I am just learning on how to use Web API with angular but I am having a few issues on retrieving data and I would appreciate it if someone could help me.
I have a controller called GetUserController with the following methods.
public class GetUserController : ApiController
{
[HttpGet]
public string GetUserName()
{
var user = "John Doe"
return user;
}
[HttpGet]
public string GetUserName2()
{
string user = "Jane Doe";
return user;
}
}
//Angular side of things
function getUser() {
return $http.get('/api/GetUser').then(function (data) {
return data;
});
}
The above code works fine and and returns the first user from the controller . however when I try to get the second by using the below angular code:
function getUser() {
return $http.get('/api/GetUser/GetUserName2').then(function (data) {
return data;
});
}
This does not work for some reason it says it can't find the GetUserName2 method. Am I missing something ? Please help?
EDIT: The error i'm getting is : Multiple actions were found that match the request
As #shammelburg has pointed out, this is as a result of Web.API not being able to match your request to a controller/method.
It's not so much that it's not RESTful, and has nothing to do with the verb you are using... it's just that an appropriate route map was not found.
Per the accepted answer, you can add another generic route map to enable the method of access you are attempting, however a more specific option exists using attribute routing:-
public class GetUserController : ApiController
{
[Route("api/getuser")]
[HttpGet]
public string GetUserName()
{
var user = "John Doe"
return user;
}
[Route("api/getuser/getusername2")]
[HttpGet]
public string GetUserName2()
{
string user = "Jane Doe";
return user;
}
}
And to enable the use of attribute routes, add this to your WebApiConfig class:-
config.MapHttpAttributeRoutes();
This method allows you to setup specific custom mappings of URLs to controllers/methods at the individual method level, without having to make a global route map that may conflict with something else in your application at a later date.
You can find more info on attribute routing here
Whilst the above will resolve the specific issue you are having, there would in practice be a different way to implement the example you gave:-
public class GetUserController : ApiController
{
[Route("api/user/{id}")]
[HttpGet]
public string GetUserName(int id)
{
// this would be replaced with some sort of data lookup...
var user = "unknown";
if (id == 1) {
user = "John Doe";
} else if (id == 2) {
user = "Jane Doe";
} // and so on...
return user;
}
}
In the above, the URL api/user/x where x is a number, e.g. api/user/1 will match the GetUserName method of the GetUserController and pass the number as an argument to the method.
This would be accessed using something like this in Angular:-
function getUser(id) {
return $http.get('/api/user/' + id).then(function (data) {
return data;
});
}
This is caused because it is not a true RESTful call which use HTTP verbs, GET, POST, PUT, DELETE.
The way to get your code to work is by altering your WebApiConfig.cs file.
From:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
To:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
As you can see we've added the {action} to the routeTemplate which makes this very much like a MVC Controller.
This allows you to call your API methods (GetUserName & GetUserName2) name like you are trying to do in your angular $http function.
Example:
return $http.get('/api/GetUser/GetUserName')
return $http.get('/api/GetUser/GetUserName2')

Resources