Adding Child to an existing parent in Webapi odata controller - post

I using Odata Webapi with EF6 and my models are as below
public class Company
{
Public Company()
{
Products = new List<Product>();
}
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public List<Product> Products { get; set; }
}
public class Product
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
I need to expose an end point to add product/s to an existing Company.
the end point has to be something like below.
Post: ~odata/Company(1)/Products with body as List of products json.
body:[{"Name":"Product1"},{"Name":"Product2"}]

I would suggest using an bound ODataAction for this purpose.
You would need to pass in a DTO containing a list of Products.
An example for DTO would be:
public class CreateProductsDTO
{
List<Product> Products { get; set; }
}
Then you would need to register an bound action to Company controller:
var action = builder.EntityType<Company>().Action("AddProducts");
action.Parameter<CreateProductsDTO>("Value");
In the controller you need to define an action like:
[HttpPost]
public async Task<IHttpActionResult> AddProducts([FromODataUri] Guid key, ODataActionParameters parameters)
{
//read parameter from ODataActionParameters
var createProducts = parameters["Value"] as CreateProductsDTO;
//Process information
}
The request for this would look like this:
Post: ~odata/Company(1)/AddProducts
body:
{ "Value" : {
"Products" :
[{"Name":"Product1"},{"Name":"Product2"}]
}
}
Hope this helps.
Regards,
Mihai

Related

repeater foreach in asp.net mvc

I'm building a website in ASP.Net, using MVC, and need to list a set of results
but i get error in the code
model:
public class Customers
{
public int Id { get; set; }
public string Name { get; set; }
public List<Customers> Itemlst { get; set; }
}
controller:
public ActionResult List()
{
Customers itemobj = new Customers();
return View(itemobj);
}
view:
#foreach(var item in Model.Itemlst)
{
<tr>
<td>Items ID:</td>
<td>#item.ID</td>
<td>Items Name:</td>
<td>#item.Name</td>
</tr>
}
</table>
From the NullReferenceException that you are receiving we can see that the issue is because of the Itemlst not being initialised. One of the ways to solve this is just to make sure that there is a valid list when you create the object:
public class Customers
{
public Customers()
{
Itemlst = new List<Customers>();
}
public int Id { get; set; }
public string Name { get; set; }
public List<Customers> Itemlst { get; set; }
}
So you can add values to the list in your action if need:
public ActionResult List()
{
Customers itemobj = new Customers();
var example = new Customers ();
example.Id = 1;
example.Name = "Example";
itemobj.Add();
return View(itemobj);
}
I don't know if you are just using this as an example for your question, but I can't help but notice that there is something weird. You could use something different like:
public class ViewModel // Name to what makes sense to you
{
// Some other properties...
public List<Customer> Customers { get; set; }
}
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
}
Or you could just use List<Customer> as your model in the view directly (yes, your model can be a object which is simply a list of objects).
When you pass the Customers list to the view, this list itself is the model.
Change Model.Itemlst —> Model inside the foreach loop.
This will iterate the list of customers.

Model binding Asp net core 2.2

I have the following complex model:
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public int UserId { get; set; }
}
I need to bind the whole model in my action method using [FromBody], while Id property should come [FromQuery]. My action method looks like this:
public IActionResult Delete([FromBody]User userRequest)
{
// Some code
}
The thing is that I can't change the model, because it is 3-rd party and also, I can't have Id as the second parameter in action method, because I have validation logic for userRequest where I need the Id. Any ideas?
Use a DTO/view model and map over to User. For example:
public class UserDTO
{
public string UserName { get; set; }
public int UserId { get; set; }
}
Then:
public IActionResult Delete(int id, [FromBody]UserDTO userRequest)
{
var user = new User
{
Id = id,
UserName = userRequest.UserName,
UserId = userRequest.UserId
}
// do something
}

MVC 4: building composite viewmodel

I am new to ASP.NET MVC. I need to build a composite viewmodel out of three nested or cascading classes: Sport>Tournament>TournamentEvent
public class Sport
{
public int Id { get; set; }
public string SportName { get; set; }
public virtual ICollection<Tournament> Tournaments { get; set; }
}
public class Tournament
{
public int Id { get; set; }
public string TournamentName { get; set; }
public int SportId { get; set; }
public virtual ICollection<TournamentEvent> TournamentEvents { get; set; }
}
public class TournamentEvent
{
public int Id { get; set; }
public string EventName { get; set; }
public int TournamentId { get; set; }
}
As you can gather, each sport contains a collection of tournaments and each tournament contains a collection of events. I need to construct an unordered list, like so:
<li> Soccer
<li>English Premier League
<li>Chelsea v Arsenal</li>
</li>
</li>
I need to build a composite viewmodel, using linq, to pass to my view, but I just can't figure it out. Please help
Don't you just need a parent vie model that contains a list of Sport?
public class Sport
{
public List<Sport> Sports { get; set; }
}
You can iterate through the collections using razor.
Can you clarify where you think linq comes into it? I might have got the wrong end of the stick.
I don't think that works, tom. I need access to the Tournament and TournamentEvent classes and I need to load them into my object, which is where linq comes in. In the SportsController:
public partial class SportsController : Controller
{
private MyDb db = new MyDb();
public virtual ActionResult Index()
{
var menuObject = from s in db.Sports
select s;
return View(menuObject);
}
}
Create a class call it SportTournamentEventViewModel.cs
using "LibraryName".Models;
public class SportTournamentEventViewModel
{
public List<Sport> Sports {get;set;}
public List<Tournament> Tournaments {get;set;}
public List<TournamentEvent> Events {get;set;}
}
in your action
private NameOfEntities db = new NameOfEntities();
public ActionResult "ActionResultName"()
{
db.Configuration.LazyLoading = false;
var sportList = db.Sport.ToList();
var tournamentList = db.Tournament.ToList();
var eventList = db.TournamentEvents.ToList();
var viewModel = new SportTournamentViewModel
{
Sports = sportList,
Tournaments = tournamentList,
Events = eventList,
};
return View(viewModel);
}

Display data from multiple models in one view

In the MVC 3 i want to display data from two models viz. Student and Enrollment into a single view.
Student model
public class Student
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int student_id { get; set; }
public string student_name { get; set; }
public string father { get; set; }
}
Enrollment model
public class Enrollment
{
[Key]
public int enrollment_id { get; set; }
public string rollno { get; set; }
public int student_id { get; set; }
public string registration_no { get; set; }
public date registration_date { get; set; }
}
My ViewModel looks like this
public class StudentEnrollmentViewModel
{
public Student_Info Student_Info { get; set; }
public Enrollment_Info Enrollment_Info { get; set; }
[Key]
public int ID { get; set; }
}
How do I retrieve the data from the two model and assign it to a viewmodel so that I can display it in a view? I am using Repository Design Pattern.
Generally speaking, a controller would be responsible for contacting the model, storing the result set returned in a variable/array/struc that the view would consume. The model and view components/classes would be registered in the controller.
An example:
<event-handler event="display.institutions" access="public">
<notify listener="userInstitutionRights" method="getInstitutionsWithDataRightsNOXML" resultKey="request.institutions" />
<view-page name="userNav" contentKey="request.userNav"/>
<view-page name="userInstitutions" contentKey="request.pageContent"/>
<announce event="assemblePage" />
</event-handler>
Event display.institutions is calling a model component userInstitutionRights and storing the result in a resultKey request.institutions and is including two view pages userNav, userInstitutions where the resultKey is available to each.
You can use DynamicPage, Look into following example
We need to use a Dynamic view page. (More Information)
Follow following steps:
Create DynamicViewPage type
public class DynamicViewPage : ViewPage
{
public new dynamic Model { get; private set; }
protected override void SetViewData(ViewDataDictionary viewData)
{
base.SetViewData(viewData);
Model = ViewData.Model;
}`
}
Your Controller will look like
public ActionResult Account(string returnUrl)
{
LoginModel loginmodel = null;//Initialize Model;
RegistrationModel registrationModel = null ;//Initialize Model;
// Any Extra logic
return View("Account", new
{
Login = loginmodel,
Register = registrationModel
});
}
your View should Inherit from
Inherits="DynamicViewPage"
Now #Model.Login will give you Loginmodel
#Model.Register will give you RegisterModel
It should work as you expected.........

Mapping with automapper

I have a domain model:
public class Project
{
[Key]
public int ProjectID { get; set; }
public string Title { get; set; }
public string Slug { get; set; }
public string Content { get; set; }
public string Category { get; set; }
public string Client { get; set; }
public int Year { get; set; }
}
I have a view model (which is a portion of the above model):
public class ListProjectsViewModel
{
public IEnumerable<ProjectStuff> SomeProjects { get; set; }
public class ProjectStuff
{
public int ProjectID { get; set; }
public string Title { get; set; }
public string Slug { get; set; }
public string Content { get; set; }
}
// Some other stuff will come here
}
I have an action controller:
public ActionResult List()
{
// Get a list of projects of type IEnumerable<Project>
var model = m_ProjectBusiness.GetProjects();
// Prepare a view model from the above domain entity
var viewModel = Mapper.Map..........
return View(viewModel);
}
How can I code the mapping '........' with automapper ?
Thanks.
There are two steps.
1) Define a mapping with AutoMapper (this is usually done in some sort of bootstrapper called by Global.asax, etc.)
// since all of your properties in Project match the names of the properties
// in ProjectStuff you don't have to do anything else here
Mapper.CreateMap<Project, ListProjectsViewModel.ProjectStuff>();
2) Map the object in your controller:
// Get a list of projects of type IEnumerable<Project>
var projects = m_ProjectBusiness.GetProjects();
// Prepare a view model from the above domain entity
var viewModel = new ListProjectsViewModel
{
SomeProjects = Mapper.Map<IEnumerable<Project>, IEnumerable<ListProjectsViewModel.ProjectStuff>>(projects)
};
return View(viewModel);
The thing to note here is that you are defining a mapping between Project and ProjectStuff. What you are trying to map is a list of Projects (IEnumerable) to a list of ProjectStuff (IEnumerable). AutoMapper can do this automatically by putting that in the generic arguments as I did above. Your View Model that your view is using is wrapping your list of ProjectStuff, so I just create a new ListProjectsViewModel and do the mapping inside of that.

Resources