asp.net web api wrong serialization output - asp.net-web-api

I inherited a model written in VB.NET that I'm trying to expose as a REST service. I have a class that inherits from a base abstract class. When I try to return a collection of the concrete class, what I get is an empty json representation like this:
[{},{},{},{},{},{},{}]
Why is this? Is it because of abstract class? I'm using MVC 4 RC. My code:
Abstract class:
<Serializable()> _
Partial Public MustInherit Class Topic
Public Property Topic_Key() As Integer
Get
Return m_Topic_Key
End Get
Set(ByVal value As Integer)
m_Topic_Key = value
End Set
End Property
End Class
Concrete class:
<Serializable()> _
Public Class ProductPortfolio
Inherits Topic
End Class
Api Controller:
public class PortfoliosController : ApiController
{
public List<ProductPortfolio> Get()
{
return ProductPortfolio.GetAll().ToList();
}
}

Put this on your abstract class
<System.Runtime.Serialization.KnownType(GetType(ProductPortfolio))>

Related

Is it considered a good practice using classes that extend an abstract class as #RequestBody?

I´m working on a legacy spring boot project that makes a strong reuse of a DTO class in a generic controller and in multiple services:
#PostMapping
controller.input(#RequestBody MyTypeDto type) { ... }
service.resolve(MyTypeDto type) { ... }
processor.send(MyTypeDto type) { ... }
I want to start decoupling it by creating another endpoint and making MyTypeDto an abstract class.
My biggest concern under all is the compatility with jackson.
public abstract class MyTypeDto { ... }
public class AnotherTypeDto extends MyTypeDto { ... }
public class AndAnotherTypeDto extends MyTypeDto { ... }
Is it considered a good practice?
As it is implied on your question, you controller endpoint is generic, it takes the input, creates the type, pass it to service based on subtype. Otherwise, you will end up many endpoints which all doing is creating the subtype and pass it to service.
If Jackson is your concern, Jackson has mechanism for subtypes. Please note you have to send one additional field which act as the discriminator (in this example, it is called type to decide which sub type to create.
#JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type")
#JsonSubTypes({#JsonSubTypes.Type(value = FirstSubDto.class, name = "First"),
#JsonSubTypes.Type(value = SecondSubDto.class, name = "Second")})
public abstract class MyTypeDto {
..
}

Copy properties from source to target class using beanutils.properties method

I have a source class Entity having some params and a target class Dto class.
Now, Entity class is having params of some other class but in dto class I'm using those params directly not using the other class reference in dto.
Problem is : while doing BeanUtils.copyProperties(source,target) those properties having reference to other class does not get copies to dto class.
Entity class:
Public class Entity{
private A a;
private String add;
}
Public class A{
private String name;
}
Dto class :
public class Dto{
private String add;
private String name; // here instead of class A i directly took the param of class A as per requirement.
}
How can I do BeanUtils.copyProperties(Entity,Dto); so that all properties get copied.
The entity class contains params from other entity class but dto does not contain the reference to other class instead directly having other class params.
Spring has the concept of Converters that are used automatically when it has to convert between classes. BeanUtils.copyProperties doesn't seem to use it, but it's should be difficult using BeanWrapper to write an alternative that loops over properties and attempts to use Converters (in this case a Converter from A to String) to copy the properties.
Alternatively there are other libraries that can do similar tasks: Dozer, ModelMapper, MapStruct just to name a few without any preference.

How can I put an instance of an object as session attribute in a Spring MVC project?

I am working on a Spring MVC application and I have the following problem.
I have this RegistrazioneInfo class that contains some information inserted into a form by the user:
public class RegistrazioneInfo {
#NotNull
#Size(min=16, max=16)
private String codiceFiscale;
String gRecaptchaResponse;
public String getCodiceFiscale() {
return codiceFiscale;
}
public void setCodiceFiscale(String codiceFiscale) {
this.codiceFiscale = codiceFiscale;
}
public String getgRecaptchaResponse() {
return gRecaptchaResponse;
}
public void setgRecaptchaResponse(String gRecaptchaResponse) {
this.gRecaptchaResponse = gRecaptchaResponse;
}
}
Then I have this controller class:
#Controller
public class RegistrazioneController extends BaseController {
private RegistrazioneInfo registrazioneInfo;
...............................................
...............................................
...............................................
}
that contains some methods handling request towards some resources.
Ok, my problem is that I want to use an instance of the previous RegistrazioneInfo class as session attribute by the use of the #SessionAttributes Spring annotation as shown here: http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-ann-sessionattrib
My problem is, in the previous example do something like this:
#SessionAttributes("pet")
public class EditPetForm {
// ...
}
So what exactly is pet? I think that it is something like an id that identify the object that have to be used as a session attribute or something like this. How can I say to put an instance of my RegistrazioneInfo as session attribute?
#SessionAttributes is declared in a Controller Class (#Controller), so on the class level.
Pet is an Bean Object that persist in HttpSession
From the documentation:
This will typically list the names of model attributes which should be transparently stored in the session or some conversational storage, serving as form-backing beans. Declared at the type level, applying to the model attributes that the annotated handler class operates on.
(emphasis is mine)
Also note that, as indicated in the documentation, you should not use that for "non temporary" elements.

Generic Request Param (runtime construction)

My requests look like:
http://...
?type[A].size=14
&type[B].query=test
My #Controller has a method which should accept those generic request params:
#RequestMapping(...)
public void test(MyModel m) {
...
}
public static class MyModel {
Map<String, ?> type;
}
The problem is: ? should be some class which is defined by the key of the Map.
This means: key=A should Map to class A and key=B should map to class B. According to the given request above: Class A will have a property int size and class B will have a property String query.
I just can't figure out, how I can tell Spring to use class A for key A and class B for key B.
(I know I could do it with POST and Jackson, but I'd like to solve this using a GET request).
Thanks for your help :)

Project Naming Convention Feedback Please

I am creating a ASP.NET MVC 3 application using Entity Framework 4. I am using the Repository/Service Pattern and was looking for feedback.
I currently have the following:
MVC Application (GTG.dll)
GTG
GTG.Controllers
GTG.ViewModels
Business POCO's (GTG.Business.dll)
This contains all business objects (Customer, Order, Invoice, etc...)
EF Model/Repositories (GTG.Data.dll)
GTG.Business (GTG.Context.tt) I used the Entity POCO Generator Templates.
GTG.Data.Repositories
Service Layer (GTG.Data.Services.dll)
GTG.Data.Services - Contains all of the service objects, one per aggregate root.
The following is a little sample code:
Controller
Namespace Controllers
Public Class HomeController
Inherits System.Web.Mvc.Controller
Function Index() As ActionResult
Return View(New Models.HomeViewModel)
End Function
End Class
End Namespace
Model
Namespace Models
Public Class HomeViewModel
Private _Service As CustomerService
Public Property Customers As List(Of Customer)
Public Sub New()
_Service = New CustomerService
_Customers = _Service.GetCustomersByBusinessName("Striano")
End Sub
End Class
End Namespace
Service
Public Class CustomerService
Private _Repository As ICustomerRepository
Public Sub New()
_Repository = New CustomerRepository
End Sub
Function GetCustomerByID(ByVal ID As Integer) As Customer
Return _Repository.GetByID(ID)
End Function
Function GetCustomersByBusinessName(ByVal Name As String) As List(Of Customer)
Return _Repository.Query(Function(x) x.CompanyName.StartsWith(Name)).ToList
End Function
End Class
Repository
Namespace Data.Repositories
Public Class CustomerRepository
Implements ICustomerRepository
Public Sub Add(ByVal Entity As Business.Customer) Implements IRepository(Of Business.Customer).Add
End Sub
Public Sub Delete(ByVal Entity As Business.Customer) Implements IRepository(Of Business.Customer).Delete
End Sub
Public Function GetByID(ByVal ID As Integer) As Business.Customer Implements IRepository(Of Business.Customer).GetByID
Using db As New GTGContainer
Return db.Customers.FirstOrDefault(Function(x) x.ID = ID)
End Using
End Function
Public Function Query(ByVal Predicate As System.Linq.Expressions.Expression(Of System.Func(Of Business.Customer, Boolean))) As System.Linq.IQueryable(Of Business.Customer) Implements IRepository(Of Business.Customer).Query
Using db As New GTGContainer
Return db.Customers.Where(Predicate)
End Using
End Function
Public Sub Save(ByVal Entity As Business.Customer) Implements IRepository(Of Business.Customer).Save
End Sub
End Class
End Namespace
The separation of your project is very good and contains exactly the layers it should. The problem is that you have a strong coupling between your layers making your code impossible to unit test.
Examples:
Your view model is strongly coupled to a specific implementation of the service:
_Service = New CustomerService
Your service is strongly coupled to a specific implementation of the repository:
_Repository = New CustomerRepository
To improve this code and weaken the coupling you should consider using constructor injection and a DI framework.
So for example have your service constructor would take a ICustomerRepository argument and assign the private field to it instead of hardcoding a new instance manually. Also have your service implement an interface and do the same constructor injection in your HomeController constructor so that it has access to the service.

Resources