Reputation: 161
I have upgraded from MVC/AngularJS 1.x to DotNet Core 2.2/Angular 6.x. with @angular/common/http
Mostly it has been a breeze but the Web API is killing me. I got the get to work in a few minutes, but I have spent a week trying everything under the sun to get the Web Post to work.
What I have done here is really simple to replicate.
Go into Visual Studio 17 and clicked File/New Project
Choose Installed/Visual C#/.NET Core
Select the template: ASP.NET core Web Application
On the secondary screen set the dropdowns at the top to .NET Core and ASP.NET Core 2.2
Select the Red shield "A" Angular template
Let the project pull down the dependencies and rebuild.
EVERYTHING is the stock out of the box demo app from Microsoft except for:
Add the buttons to the screen.
Add code to the .ts to call the API Controller
Add the input parm to the get method in the controller
Add a very simple post method to the controller
I am also am trying to get DotNet Core 2.0/Angular 4.x. with @angular/http to work with the exact same results. The get was very easy, but I have tried every configuration under the sun to get the post to work. I will make a post like this for the other version as well. Right now, I am just trying to get whatever I can to work and leave AngularJS 1.x behind.
import { Component, Inject } from '@angular/core';
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
@Component({
selector: 'app-fetch-data',
templateUrl: './fetch-data.component.html'
})
export class FetchDataComponent {
public Http: HttpClient;
public BaseURL: string;
public HttpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
public startDateIndex = 0;
public forecasts: WeatherForecast[] = [];
public forecast: WeatherForecast = {
dateFormatted: "3/27/2020",
temperatureC: 0,
temperatureF: 32,
summary: "Cold Post"
};
constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
this.Http = http;
this.BaseURL = baseUrl;
http.get<WeatherForecast[]>(baseUrl + 'api/SampleData/WeatherForecasts')
.subscribe(result => { this.forecasts = result; }, error => console.error(error));
}
public OnClick(pControl: string) {
//console.log("LogOn.OnClick * pControl=" + pControl);
switch (pControl) {
case "Prior":
this.startDateIndex -= 5;
this.Http.get<WeatherForecast[]>(this.BaseURL + 'api/SampleData/WeatherForecasts/', { params: new HttpParams().set('startDateIndex', this.startDateIndex.toString()) })
.subscribe(result => { this.forecasts = result; }, error => console.error(error));
break;
case "Next":
this.startDateIndex += 5;
this.Http.get<WeatherForecast[]>(this.BaseURL + 'api/SampleData/WeatherForecasts/', { params: new HttpParams().set('startDateIndex', this.startDateIndex.toString()) })
.subscribe(result => { this.forecasts = result; }, error => console.error(error));
break;
case "Post":
console.log("Post * this.forecast=" + JSON.stringify(this.forecast) + "this.HttpOptions=" + JSON.stringify(this.HttpOptions));
this.Http.post<WeatherForecast>(this.BaseURL + '/api/SampleData/PostWeatherForecast/', this.forecast, this.HttpOptions);
}
}
}
interface WeatherForecast {
dateFormatted: string;
temperatureC: number;
temperatureF: number;
summary: string;
}
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from the server.</p>
<p *ngIf="!forecasts"><em>Loading...</em></p>
<table class='table table-striped' *ngIf="forecasts">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let forecast of forecasts">
<td>{{ forecast.dateFormatted }}</td>
<td>{{ forecast.temperatureC }}</td>
<td>{{ forecast.temperatureF }}</td>
<td>{{ forecast.summary }}</td>
</tr>
</tbody>
</table>
<button class='btn btn-default pull-left' (click)="OnClick('Prior')">Previous</button>
<button class='btn btn-default pull-left' (click)="OnClick('Next')">Next</button>
<button class='btn btn-default pull-right' (click)="OnClick('Post')">Post</button>
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
namespace NG_22.Controllers
{
[Route("api/[controller]")]
public class SampleDataController : Controller
{
private static string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
[HttpGet("[action]")]
public IEnumerable<WeatherForecast> WeatherForecasts(int startDateIndex = 0)
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
DateFormatted = DateTime.Now.AddDays(index + startDateIndex).ToString("d"),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
});
}
[HttpPost("[action]")]
public WeatherForecast PostWeatherForecast([FromBody] WeatherForecast weatherForecast)
{
var forecast = weatherForecast;
//return weatherForecast;
return new WeatherForecast()
{
DateFormatted = DateTime.Now.ToString("d"),
TemperatureC = 30,
Summary = Summaries[2]
};
}
public class WeatherForecast
{
public string DateFormatted { get; set; }
public int TemperatureC { get; set; }
public string Summary { get; set; }
public int TemperatureF
{
get
{
return 32 + (int)(TemperatureC / 0.5556);
}
}
}
}
}
Upvotes: 2
Views: 4756
Reputation: 161
using D2Chess.Server.IO;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
namespace D2Chess.Controllers
{
[Route("api/[controller]/[action]")]
public class WebController : Controller
{
#region Init
private JsonSerializer jsonSerializer = new JsonSerializer();
private Repository repository = new Repository();
public WebController(IHubContext<D2Chess.Server.IO.Hub> hubContext) { D2Chess.Server.IO.Hub.StaticContext = hubContext; }
#endregion
#region Classes
public class Parms {
public Guid? TokenId { get; set; }
public string Action { get; set; }
public object Data { get; set; }
}
public class Result
{
public bool Success { get; set; }
public object Data { get; set; }
public Result(bool pSuccess, object pData = null) { this.Success = pSuccess; this.Data = pData; }
}
#endregion
#region Sync Methods
[HttpGet]
public object Get(string pAction, string pKey = "", Guid? pTokenId = null)
{
return repository.WebGet(pAction, pKey, pTokenId);
//var result = repository.WebGet(pAction, pKey, pTokenId);
//return result;
}
[HttpPost]
public object Post([FromBody] object pParms)
{
var parms = ((JObject)pParms).ToObject<Parms>();
return repository.WebPost(parms.Action, parms.Data, parms.TokenId);
//var result = repository.WebPost(parms.Action, parms.Data, parms.TokenId);
//return result;
}
#endregion
}
}
Upvotes: 0
Reputation: 161
using DMChess_Data.Model;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace DMChess_Data
{
public class Entities
{
private dmchessContext DMCConnection = new dmchessContext();
private Guid AppId = new Guid("B6C093C8-AE8C-40CD-9E0D-3BD2118422EC");
public bool SaveChanges()
{
try
{
DMCConnection.SaveChangesAsync();
}
catch(Exception pException)
//catch (Microsoft.EntityFrameworkCore.)
//catch (System.Data.Entity.Validation.DbEntityValidationException ex)
{
var ex = pException;
//foreach (var eve in ex.EntityValidationErrors)
//{
// var type = eve.Entry.Entity.GetType().Name;
// var state = eve.Entry.State;
// foreach (var ve in eve.ValidationErrors)
// {
// var propertyName = ve.PropertyName;
// var ErrorMessage = ve.ErrorMessage;
// }
//}
//var m = ex;
throw;
}
DMCConnection.SaveChanges();
return true;
}
#region AUsers
public AUsers AUsersGet(Guid pId, string pPassword)
{
return DMCConnection.AUsers.FirstOrDefault(x => x.KAppId == AppId && x.KId == pId && x.Password == pPassword);
}
public AUsers AUsersGet(string pEmailAddress, string pPassword)
{
return DMCConnection.AUsers.FirstOrDefault(x => x.KAppId == AppId && x.EmailAddress == pEmailAddress);
}
#endregion
#region DProfiles
public DProfiles DProfileGet(Guid pKUserId, int pKIdx)
{
return DMCConnection.DProfiles.FirstOrDefault(x => x.KAppId == AppId && x.KUserId == pKUserId && x.KIdx == pKIdx);
}
public List<DProfiles> DProfilesGet(string pUserIdName)
{
return DMCConnection.DProfiles.Where(x => x.KAppId == AppId && x.UserIdToLower == pUserIdName.ToLower()).ToList();
}
#endregion
}
}
Upvotes: 0
Reputation: 161
Solved it!!!!!
The problem was that there nothing subscribing. If no one is listening, it doesn't bother calling the Post. I added a .subscribe and it worked fine.
import { Component, Inject } from '@angular/core';
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
@Component({
selector: 'app-fetch-data',
templateUrl: './fetch-data.component.html'
})
export class FetchDataComponent {
public Http: HttpClient;
public BaseURL: string;
public HttpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
public startDateIndex = 0;
public forecasts: WeatherForecast[] = [];
public forecast: WeatherForecast = {
dateFormatted: "3/27/2020",
temperatureC: 0,
temperatureF: 32,
summary: "Cold Post"
};
constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
this.Http = http;
this.BaseURL = baseUrl;
http.get<WeatherForecast[]>(baseUrl + 'api/SampleData/WeatherForecasts')
.subscribe(result => { this.forecasts = result; }, error => console.error(error));
}
public OnClick(pControl: string) {
//console.log("LogOn.OnClick * pControl=" + pControl);
switch (pControl) {
case "Prior":
this.startDateIndex -= 5;
this.Http.get<WeatherForecast[]>(this.BaseURL + 'api/SampleData/WeatherForecasts/', { params: new HttpParams().set('startDateIndex', this.startDateIndex.toString()) })
.subscribe(result => { this.forecasts = result; }, error => console.error(error));
break;
case "Next":
this.startDateIndex += 5;
this.Http.get<WeatherForecast[]>(this.BaseURL + 'api/SampleData/WeatherForecasts/', { params: new HttpParams().set('startDateIndex', this.startDateIndex.toString()) })
.subscribe(result => { this.forecasts = result; }, error => console.error(error));
break;
case "Post":
console.log("Post * this.forecast=" + JSON.stringify(this.forecast) + "this.HttpOptions=" + JSON.stringify(this.HttpOptions));
this.Http.post<WeatherForecast>(this.BaseURL + '/api/SampleData/PostWeatherForecast/', this.forecast, this.HttpOptions)
.subscribe(result => { console.log("Posted" + JSON.stringify(result)); }, error => console.error(error));
}
}
}
interface WeatherForecast {
dateFormatted: string;
temperatureC: number;
temperatureF: number;
summary: string;
}
Upvotes: 5
Reputation: 161
Improved answer. The Interface is not necessary and other smaller refinements and removal of unnecessary code.
import { Component, Inject } from '@angular/core';
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
@Component({
selector: 'app-fetch-data',
templateUrl: './fetch-data.component.html'
})
export class FetchDataComponent {
public Http: HttpClient;
public BaseURL: string;
public HttpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
public startDateIndex = 0;
public forecasts: any;
public forecast = { dateFormatted: "3/27/2020", temperatureC: 0, temperatureF: 32, summary: "Cold Post", Data: { color: "red", Size: "Large" } };
constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
this.Http = http;
this.BaseURL = baseUrl;
http.get(baseUrl + 'api/SampleData/WeatherForecasts')
.subscribe(result => { this.forecasts = result; }, error => console.error(error));
}
public OnClick(pControl: string) {
//console.log("LogOn.OnClick * pControl=" + pControl);
switch (pControl) {
case "Prior":
this.startDateIndex -= 5;
this.Http.get(this.BaseURL + 'api/SampleData/WeatherForecasts/', { params: new HttpParams().set('startDateIndex', this.startDateIndex.toString()) })
.subscribe(result => { this.forecasts = result; }, error => console.error(error));
break;
case "Next":
this.startDateIndex += 5;
this.Http.get(this.BaseURL + 'api/SampleData/WeatherForecasts/', { params: new HttpParams().set('startDateIndex', this.startDateIndex.toString()) })
.subscribe(result => { this.forecasts = result; }, error => console.error(error));
break;
case "Post":
console.log("Post * this.forecast=" + JSON.stringify(this.forecast) + "this.HttpOptions=" + JSON.stringify(this.HttpOptions));
this.Http.post(this.BaseURL + '/api/SampleData/PostWeatherForecast/', this.forecast, this.HttpOptions)
.subscribe(result => { alert("Posted" + JSON.stringify(result)); }, error => console.error(error));
}
}
}
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from the server.</p>
<p *ngIf="!forecasts"><em>Loading...</em></p>
<table class='table table-striped' *ngIf="forecasts">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let forecast of forecasts">
<td>{{ forecast.dateFormatted }}</td>
<td>{{ forecast.temperatureC }}</td>
<td>{{ forecast.temperatureF }}</td>
<td>{{ forecast.summary }}</td>
</tr>
</tbody>
</table>
<button class='btn btn-default pull-left' (click)="OnClick('Prior')">Previous</button>
<button class='btn btn-default pull-left' (click)="OnClick('Next')">Next</button>
<button class='btn btn-default pull-right' (click)="OnClick('Post')">Post</button>
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
namespace NG_22.Controllers
{
[Route("api/[controller]/[action]")]
public class SampleDataController : Controller
{
private static string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
[HttpGet]
public IEnumerable<WeatherForecast> WeatherForecasts(int startDateIndex = 0)
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
DateFormatted = DateTime.Now.AddDays(index + startDateIndex).ToString("d"),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
});
}
[HttpPost]
public object PostWeatherForecast([FromBody] WeatherForecast weatherForecast)
{
var forecast = weatherForecast;
//return weatherForecast;
return new
{
DateFormatted = DateTime.Now.ToString("d"),
TemperatureC = 30,
Summary = Summaries[2]
};
}
public class WeatherForecast
{
public string DateFormatted { get; set; }
public int TemperatureC { get; set; }
public string Summary { get; set; }
public int TemperatureF
{
get
{
return 32 + (int)(TemperatureC / 0.5556);
}
}
public object Data { get; set; }
}
}
}
Upvotes: 2