Here is @Nkosi's answer translated to VB.Net.
I am building a WebAPI2 backend to support TourOfHeroes.
I imagine case where I have a 'heavy' object and I dont want to return all properties to all views. Imagine Hero had ~30 columns and I only need Id and Name for the Heroes.component.ts....
I dont want to additionally create an object to represent each view just so I can JSON serialize them... DRY?
So, here are the 2 classes that @NKosi posted. Not sure the shared class is necessary, I just implemented as @NKosi wrote it.
Imports System.Net.Http
Imports System.Web.Http
Imports System.Net
Imports System.Threading
Imports System.Threading.Tasks
Public Class JsonStringResultExtension
Public Shared Function JSONString(Controller As ApiController,
Optional jsonContent As String = "",
Optional statusCode As HttpStatusCode = HttpStatusCode.OK) As CustomJsonStringResult
Dim result As New CustomJsonStringResult(Controller.Request, statusCode, jsonContent)
Return result
End Function
End Class
Public Class CustomJsonStringResult
Implements IHttpActionResult
Private json As String
Private statusCode As HttpStatusCode
Private request As HttpRequestMessage
Public Sub New(httpRequestMessage As HttpRequestMessage, Optional statusCode As HttpStatusCode = HttpStatusCode.OK, Optional json As String = "")
Me.request = httpRequestMessage
Me.json = json
Me.statusCode = statusCode
End Sub
Public Function ExecuteAsync(cancellationToken As CancellationToken) As Task(Of HttpResponseMessage) Implements IHttpActionResult.ExecuteAsync
Return Task.FromResult(Execute())
End Function
Private Function Execute() As HttpResponseMessage
Dim response = request.CreateResponse(statusCode)
response.Content = New StringContent(json, Encoding.UTF8, "application/json")
Return response
End Function
End Class
I will also add that you have to the following to webApiConfig.vb or you will get complaints that you cant parse the HTML
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(New MediaTypeHeaderValue("text/html"))
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(New MediaTypeHeaderValue("application/json"))
Here is the webAPI controller call that supports the heroes.component.js
Exactly like @Luis Abreu, my BOs are already returning JSON. I just want to return the correctly formed JSON as a string, as opposed to mapping my BO into another class here in the API for the sole purpose of serializing it...
<HttpGet>
<Route("")>
Public Function GetAllHeroes() As CustomJsonStringResult
'populate a list of heros however you want
dim ag as new HeroAg()
Dim l As List(Of TOHbos.Hero) = ag.Items
'This should be shoved down into a reusable class...ListToJSON
Dim sb As New StringBuilder("")
Dim first As Boolean = True
sb.Append("[")
For Each h As TOHbos.Hero In l
If first = True Then
first = False
Else
sb.Append(", ")
End If
'decide which fields to include and generate a JSON document
h.decideWhichFieldsGetSerializedForThisView()
sb.Append(h.JSON)
Next
sb.Append("]")
Return JsonStringResultExtension.JSONString(Me, sb.ToString(), HttpStatusCode.OK)
End Function
The next problem I ran into was that I was getting this error from the angular app in the browser console
Http failure during parsing for localhost:4300/api/heroes
Using jsonLint.com ,i was able to figure out that my JSON was not quite correct. I wasn't putting the key names in double ticks, and i was putting values in single ticks. While this may be acceptable JSON, jsonLint complains, and I guess so does Angular rxjs
return Json(response);?