public class UserController : ApiController
{
UserSampleEntities entities = new UserSampleEntities();
// GET api/<controller>
[Route("api/User")]
public IEnumerable<user> Get()
{
{
return entities.users;
}
}
}
This returns the json with all the entries in the database with all its properties. How do I filter such that I can obtain a json for only specific properties?
Create a new class that represents a user using only the properties you want to expose from "api/User":
public class UserDto
{
public int Foo { get; set; }
public string Bar { get; set; }
// add the properties you need here
}
Rewrite your API action to this:
[Route("api/User")]
public IEnumerable<UserDto> Get()
{
return entities.users
.Select(u => new UserDto
{
Foo = u.Foo,
Bar = u.Bar,
// map the properties you need here
})
.ToArray();
}
Related
I have an index method in a controller which looks like this :
public ActionResult Index()
{
var object = _ObjectService.GetAll();
return View(object);
}
Which give me a list of object with those properties :
public class Object : EntityWithNameAndId
{
public virtual Site Site { get; set; }
public virtual List<User> Users { get; set; }
public virtual List<Planning> Plannings { get; set; }
public virtual Guid IdPilote { get; set; }
}
Now in my Index() view, i want to get the User who's related to the IdPilote id and display its name.
I tried something like this, thanks to this topic ASP.Net MVC: Calling a method from a view :
#model List<MyClass.Models.Promotion>
#foreach (var item in Model)
{
<td>#item.Site.Name</td>
#{
var id = item.IdPilote;
//Here Interface and Service are folders
var user = MyDAL.Interface.Service.IUserService.Get(id);
}
<td>
//This is where i try to display my User name,
//that i get dynamically using the idPilote for each User in list
</td>
}
But Get(id) is not recognize as a valid method..
public interface IUserService : IDisposable
{
User Get(Guid id);
}
public class UserService : IUserService
{
private MyContext context;
public UserService(MyContext context)
{
this.context = context;
}
public User Get(Guid id)
{
return context.User.Where(w => w.Id == id).SingleOrDefault();
}
}
So what's the best way to get my User object inside my view, since i only get an Id ?
Should i create a new list, using the first one, in my Index method (where i can call IUserInterface.Get()) or is there a better way to do it ?
Make it worked by creating a new list and a specific ViewModel, as suggested :
public class IndexObjectViewModel : EntityWithNameAndId
{
public virtual Site Site { get; set; }
public virtual List<User> Users { get; set; }
public virtual List<Planning> Plannings { get; set; }
//To store User instead of its Id
public virtual User Pilote { get; set; }
}
Now Index() looks like this :
public ActionResult Index()
{
var objects = _IObjectService.GetAll();
ViewBag.NotPromoExist = false;
var indexObj = new List<IndexObjectViewModel>();
foreach (var p in objects)
{
var indexModel = new IndexObjectViewModel();
indexModel.Id = p.Id;
indexModel.Name = p.Name;
indexModel.Site = p.Site;
indexModel.Users = p.Users;
indexModel.Plannings = p.Plannings;
indexModel.Pilote = _IUserService.Get(p.IdPilote);
indexObj.Add(indexModel);
}
return View(indexObj);
}
Everything is done in the controller now. Not sure if it's the best way to do it though..
I'm adding an API controller to my MVC application to retun JSON data
In my application I have a class called Album:
public class Album
{
public int Id { get; set; }
public string AlbumName { get; set; }
public int YearReleased { get; set; }
public string AlbumInfo { get; set; }
public string imgAlbumCover { get; set; }
}
My database contains a table of several Album objects
I created an API controller to return this list of Albums in Json format.
I added the following code to WebApiConfig.cs to get JSON back instead of XML:
using System.Net.Http.Headers;
GlobalConfiguration.Configuration.Formatters
.JsonFormatter.MediaTypeMappings.Add
(new System.Net.Http.Formatting.RequestHeaderMapping("Accept",
"text/html",
StringComparison.InvariantCultureIgnoreCase,
true,
"application/json"));
When I do an Albums API call in the browser, returned is a list of Album objects in JSON format.
Instead of returning the list of Albums, I'd like to retun a RootObject that has 1 property called Albums, where Albums is a list of Album objects. Is there a way of doing this in the controller? I don't want to have to create a new RootObject class.
Below is the code for my API controller:
namespace Music.Controllers.API
{
public class AlbumsController : ApiController
{
private MusicContext db;
public AlbumsController()
{
db = new MusicContext();
}
public IEnumerable<Album> GetAlbums()
{
return (db.Albums.ToList());
}
}
}
Then create a viewmodel as such and return the same like
public class AlbumListResponseModel
{
public IEnumerable<Album> Albums { get; set; }
}
public async Task<IActionResult> GetAlbums()
{
AlbumListResponseModel model = new AlbumListResponseModel
{
Albums = db.Albums;
}
return OK(model);
}
If you are using WEB API 2.0 then consider using IActionResult rather
Change the GetAlbums return type to HttpResponseMessage and change the return statement as
return Request.CreateResponse(HttpStatusCode.OK, new {Albums = db.Albums.ToList() });
That's way you don't need to create a new class.
Full Code :
namespace Music.Controllers.API
{
public class AlbumsController : ApiController
{
private MusicContext db;
public AlbumsController()
{
db = new MusicContext();
}
public HttpResponseMessage GetAlbums()
{
return Request.CreateResponse(HttpStatusCode.OK, new {Albums = db.Albums.ToList() });
}
}
}
I am trying to implement one model with dynamic columns.
My model:
public partial class AccountViewModel : DbContext
{
public ACCOUNT Accountdt { get; set; }
}
My controller code returning index.cshtml:
// To display grid in Kendo UI
public ActionResult Accounts_Read([DataSourceRequest]DataSourceRequest request)
{
Json(GetAccounts().ToDataSourceResult(request,ModelState));
}
//To extract data from linq
private IEnumerable<Object> GetAccounts()
{
var database = new Entities();
var load = database.ACCOUNTs.AsQueryable();
AccountViewModel avm = new AccountViewModel();
return load.Select(account => avm.Accountdt);
}
I am not able to see dataset in the result datagrid. Early it is working fine when columns are declare in the model.
Here is my code that's working fine:
public partial class AccountViewModel : DbContext
{
public string Id { get; set; }
}
// To display grid in Kendo UI
public ActionResult Accounts_Read([DataSourceRequest]DataSourceRequest request)
{
Json(GetAccounts().ToDataSourceResult(request, ModelState));
}
private IEnumerable<Object> GetAccounts()
{
var database = new Entities();
var load = database.ACCOUNTs.AsQueryable();
return load.Select(account => AccountViewModel {
id = account.id;
});
}
Change following code,
return load.Select(account => avm.Accountdt);
as follows,
return load.Select(account => new AccountViewModel {
Accountdt = account
});
I have a controller where my PUT method uses multipart/form-data as content type and so I am getting the JSON and the mapped class thereby inside the controller.
Is there a way I could validate this model with respect to the annotations I have written in the model class while inside the controller?
public class AbcController : ApiController
{
public HttpResponseMessage Put()
{
var fileForm = HttpContext.Current.Request.Form;
var fileKey = HttpContext.Current.Request.Form.Keys[0];
MyModel model = new MyModel();
string[] jsonformat = fileForm.GetValues(fileKey);
model = JsonConvert.DeserializeObject<MyModel>(jsonformat[0]);
}
}
I need to validate "model" inside the controller.
FYI, I have added required annotations to MyModel().
Manual model validation:
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
class ModelValidator
{
public static IEnumerable<ValidationResult> Validate<T>(T model) where T : class, new()
{
model = model ?? new T();
var validationContext = new ValidationContext(model);
var validationResults = new List<ValidationResult>();
Validator.TryValidateObject(model, validationContext, validationResults, true);
return validationResults;
}
}
Suppose you have defined models in Product class like :
namespace MyApi.Models
{
public class Product
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public decimal Price { get; set; }
}
}
and then inside controller just write:
public class ProductsController : ApiController
{
public HttpResponseMessage Post(Product product)
{
if (ModelState.IsValid)
{
return new HttpResponseMessage(HttpStatusCode.OK);
}
}
}
You can also use Fluent Validation to do this. https://docs.fluentvalidation.net/en/latest/aspnet.html
Your Model Class:
public class Customer
{
public int Id { get; set; }
public string Surname { get; set; }
public string Forename { get; set; }
public decimal Discount { get; set; }
public string Address { get; set; }
}
You would define a set of validation rules for this class by inheriting from AbstractValidator<Customer>:
using FluentValidation;
public class CustomerValidator : AbstractValidator<Customer>
{
RuleFor(customer => customer.Surname).NotNull();
. . . etc;
}
To run the validator, instantiate the validator object and call the Validate method, passing in the object to validate.
Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();
ValidationResult result = validator.Validate(customer);
The Validate method returns a ValidationResult object. This contains two properties:
IsValid - a boolean that says whether the validation succeeded.
Errors - a collection of ValidationFailure objects containing details about any validation failures.
The following code would write any validation failures to the console from your controller or even from your service or repository:
using FluentValidation.Results;
Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);
if(! results.IsValid)
{
foreach(var failure in results.Errors)
{
Console.WriteLine("Property " + failure.PropertyName + " failed validation. Error was: " + failure.ErrorMessage);
}
}
You can also inject the validator inside Program.cs , read here : https://docs.fluentvalidation.net/en/latest/di.html
This is my view model.
public class ProductViewModel
{
public Guid Id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public bool IsAvailable { get; set; }
}
When form is posted from client the form is submitted to this Controller
public async Task<IHttpActionResult> AddProduct(ProductViewModel productViewModel)
{
await ServiceInstances.PostAsync("product/add", productViewModel);
return Ok();
}
Then this controller submit the form to the API controller
Which is on my separate Project.
[HttpPost]
[Route("add")]
public IHttpActionResult AddProduct(ProductViewModel model)
{
_productService.AddProduct(model.UserServiceDetails());
return Ok();
}
Extension UserServiceDetails Where i get the Login User Info
public static UserServiceDetailModel<T> UserServiceDetails<T>(this T model)
{
var serviceRequestModel = new ServiceRequestModel<T>()
{
Model = model,
LoginInfo = HttpContext.Current.User.Identity.GetUserLoginInfo();
};
}
AddProductService:
public void AddProduct(UserServiceDetailModel<ProductViewModel> serviceRequestModel)
{
var repo = _genericUnitOfWork.GetRepository<Product, Guid>();
var mapped = _mapper.Map<ProductViewModel, Product>(serviceRequestModel.Model);
mapped.Id = Guid.NewGuid();
mapped.CreatedDate = GeneralService.CurrentDate();
mapped.CreatedById = serviceRequestModel.LoginInfo.UserId;
repo.Add(mapped);
_genericUnitOfWork.SaveChanges();
}
Now my question is Is there any way to assign the value to this field CreatedDate and CreatedById before posting it to service?
Reduce these logic to mapper:
mapped.CreatedDate = GeneralService.CurrentDate();
mapped.CreatedById = serviceRequestModel.LoginInfo.UserId;
Or is there any way that those field gets mapped to Product when
var mapped = _mapper.Map<ProductViewModel, Product>(serviceRequestModel.Model);
Sometime i may have the List<T> on view-model and there i have to add this field using the loop.
So this same mapping may get repeated over and over on Add Method Or Update.
In some entity i have to assign the ModifiedDate and ModifiedById also.
My Mapper Configuration:
public class ProductMapper : Profile
{
public ProductMapper()
{
CreateMap<ProductViewModel, Product>();
}
}
I cannot add the Enitity as IAuditableEntity and Overrride in ApplicationDbContext because my DbContext is in separate Project and i donot have access to Identity there.