I am currently having an API endpoint, which using EF fetches data from the database as such:
Controller:
/// <summary>
/// The View Controller Class
/// </summary>
[ApiController]
[Authorize]
[Route(ApiEndpointConfiguration.External)]
public class ViewController : ControllerBase
{
private readonly IViewService viewService;
private readonly ILogger logger;
private readonly IUserContext userContext;
/// <summary>
/// Constructs ViewController
/// </summary>
/// <param name="viewService">IViewService</param>
/// <param name="userContext">IUserContext</param>
/// <param name="loggerFactory">ILoggerFactory</param>
/// <param name="options">LoggerOptions</param>
public ViewController(
IViewService viewService,
IUserContext userContext,
ILoggerFactory loggerFactory,
LoggerOptions options)
{
this.userContext = userContext;
this.viewService = viewService;
logger = loggerFactory.CreateSystemLogger<ViewController>("Log", options);
}
/// <summary>
/// Retrieve TableViews you can view
/// OData is enabled to allow for building queries
/// </summary>
/// <returns>TableView</returns>
/// <response code="200">TableView</response>
/// <response code="401">Unauthorized</response>
/// <response code="403">Forbidden</response>
/// <response code="404">Not Found</response>
/// <response code="500">Internal Server Error</response>
[HttpGet]
[EnableQuery()]
public ActionResult Get()
{
logger.Information($"A GET request was performed by {HttpContext.Connection.Id}");
var userIdParameter = HttpContext.Request.Query["userId"];
Guid userId = string.IsNullOrEmpty(userIdParameter) ? userContext.UserId : Guid.Parse(userIdParameter);
bool isAllowed = userContext.CanExecute("AdminView");
if (!isAllowed && userContext.UserId != userId)
{
throw new InvalidPermissionsException(userContext.UserId,
"User does not have permission to get the view");
}
var views = viewService
.Get()
.Where(x => x.UserId == userId || x.UserId == null)
.ToList();
return Ok(views.ToViewModel());
}
I am able to filter the result using url as
https://localhost:5001/external/api/View?$filter=targetSystem%20eq%20%27frontpage%27%20and%20targetName%20eq%20%27car%27
But when I add count I don't see the count value anywhere?
why?
https://localhost:5001/external/api/View?$filter=targetSystem%20eq%20%27frontpage%27%20and%20targetName%20eq%20%27car%27&$count=true
in my startup.cs I have configured it as such
app.UseMvc(routeBuilder =>
{
routeBuilder.EnableDependencyInjection();
routeBuilder.Expand().Select().Count().OrderBy().Filter();
});
so count should be included? why is it not being parsed in my output?
I am interested in knowing the sql generated by odata when count is being queried, but it seems like count does not respond at all..
This is a sample OData request and response using count:
Request
https://localhost:5000/api/v1/HomepageBanner?%24filter=id%20eq%202&%24count=true
Response body
{
"#odata.context": "https://localhost:5000/api/v1/$metadata#HomepageBanner",
"#odata.count": 0,
"value": []
}
As you can see from the response, the one you are looking at is "#odata.count"
Edit:
To be honest, I can't see why you could filter but can't get the count, you could do filter means that the OData endpoint was working.
Maybe you could compare your solution with what I'm doing on my github repo?
https://github.com/martinussuherman/odata-test
Related
My team and I created a custom OAuth to be used for external SSO. It works on localhost but as soon as we take it up to our staging environment we get an "The oauth state was missing or invalid." error.
We used "https://auth0.com/" for testing.
To try and troubleshoot this we overrode the following built in methods and via breakpoints can see that Query state comes back null.
protected override string BuildChallengeUrl(AuthenticationProperties properties, string redirectUri);
protected override async Task<HandleRequestResult> HandleRemoteAuthenticateAsync();
I need some help figuring out why this is a problem on staging and not on local as we are a bit stumped. A theory we have is that the decoder used inside these methods change on var properties = Options.StateDataFormat.Unprotect(state); and thus because they aren't the same they can't decode each others states. I will put our implementation below, if its required I can paste the built in methods as well but I can't fathom the problem lying with the built in functions.
Startup:
foreach (var customAuthItem in customAuthList)
{
services.AddAuthentication().AddCustom(customAuthItem.CampaignId, options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.AuthorizationEndpoint = customAuthItem.AuthEndpoint;
options.TokenEndpoint = customAuthItem.TokenEndpoint;
options.UserInformationEndpoint = customAuthItem.UserInfoEndpoint;
options.ClientId = customAuthItem.ClientId;
options.ClientSecret = customAuthItem.ClientSecret;
});
}
Options:
public class CustomAuthenticationOptions : OAuthOptions
{
/// <summary>
/// Initializes a new instance of the <see cref="CustomAuthenticationOptions"/> class.
/// </summary>
public CustomAuthenticationOptions()
{
ClaimsIssuer = CustomAuthenticationDefaults.Issuer;
CallbackPath = CustomAuthenticationDefaults.CallbackPath;
AuthorizationEndpoint = CustomAuthenticationDefaults.AuthorizationEndpoint;
TokenEndpoint = CustomAuthenticationDefaults.TokenEndpoint;
UserInformationEndpoint = CustomAuthenticationDefaults.UserInformationEndpoint;
Scope.Add("openid");
Scope.Add("profile");
Scope.Add("email");
ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
ClaimActions.MapJsonKey(ClaimTypes.Name, "name");
ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub");
}
/// Gets the list of fields to retrieve from the user information endpoint.
/// </summary>
public ISet<string> Fields { get; } = new HashSet<string>
{
"email",
"name",
"sub"
};
Defaults:
public static class CustomAuthenticationDefaults
{
/// <summary>
/// Default value for <see cref="AuthenticationScheme.Name"/>.
/// </summary>
public const string AuthenticationScheme = "Custom";
/// <summary>
/// Default value for <see cref="AuthenticationScheme.DisplayName"/>.
/// </summary>
public static readonly string DisplayName = "Custom";
/// <summary>
/// Default value for <see cref="AuthenticationSchemeOptions.ClaimsIssuer"/>.
/// </summary>
public static readonly string Issuer = "Custom";
/// <summary>
/// Default value for <see cref="RemoteAuthenticationOptions.CallbackPath"/>.
/// </summary>
public static readonly string CallbackPath = "/signin-custom";
/// <summary>
/// Default value for <see cref="OAuthOptions.AuthorizationEndpoint"/>.
/// </summary>
public static readonly string AuthorizationEndpoint = "https://dev-egd511ku.us.auth0.com/authorize";
/// <summary>
/// Default value for <see cref="OAuthOptions.TokenEndpoint"/>.
/// </summary>
public static readonly string TokenEndpoint = "https://dev-egd511ku.us.auth0.com/oauth/token";
/// <summary>
/// Default value for <see cref="OAuthOptions.UserInformationEndpoint"/>.
/// </summary>
public static readonly string UserInformationEndpoint = "https://dev-egd511ku.us.auth0.com/userinfo";
}
Handler:
protected override async Task<AuthenticationTicket> CreateTicketAsync(
[NotNull] ClaimsIdentity identity,
[NotNull] AuthenticationProperties properties,
[NotNull] OAuthTokenResponse tokens)
{
Serilog.Log.Debug("CustomAuthenticationHandler.CreateTicketAsync: STARTED!");
string endpoint = Options.UserInformationEndpoint;
if (Options.Fields.Count > 0)
{
endpoint = QueryHelpers.AddQueryString(endpoint, "fields", string.Join(',', Options.Fields));
}
using var request = new HttpRequestMessage(HttpMethod.Get, endpoint);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokens.AccessToken);
Serilog.Log.Debug("CustomAuthenticationHandler.CreateTicketAsync: ABOUT TO SEND REQUEST!");
using var response = await Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, Context.RequestAborted);
if (!response.IsSuccessStatusCode)
{
Serilog.Log.Debug($"CustomAuthenticationHandler.CreateTicketAsync: FAILED REQUEST: {response.ReasonPhrase}");
await Log.UserProfileErrorAsync(Logger, response, Context.RequestAborted);
throw new HttpRequestException("An error occurred while retrieving the user profile from Custom.");
}
var payloadString = await response.Content.ReadAsStringAsync();
Serilog.Log.Debug($"CustomAuthenticationHandler.CreateTicketAsync: PAYLOAD: {payloadString}");
using var payload = JsonDocument.Parse(payloadString);// Context.RequestAborted));
var principal = new ClaimsPrincipal(identity);
var context = new OAuthCreatingTicketContext(principal, properties, Context, Scheme, Options, Backchannel, tokens, payload.RootElement);
context.RunClaimActions();
await Events.CreatingTicket(context);
return new AuthenticationTicket(context.Principal!, context.Properties, Scheme.Name);
}
EDIT: The error is received after successful login and after being redirected back to our site. I can see through sentry breadcrumbs that the states are correct so it seems to be a decryption issue.
It turns out the problem is because I AddAuthentication() twice, it ignores the follow-up registration of the auth methods, resulting in only one OAuth working. This is a bit of a problem because we want to support multiple SSO options for our clients, but might need to figure out a different approach. I am just glad I finally know where the problem is.
I have trying to write integration tests for my SignalR chat application.
But the connection.On() callbacks never gets fired.
While debugging I have made sure InvokeAsync works perfectly fine but not the callbacks
Also I have tested my hub with Angular client and it works fine.
Test.cs
public sealed class ChatHubTest : ControllerTests
{
private IHost? host_;
[Test]
public async Task ReplyWithTheSameMessageWhenInvokeSendMethod()
{
//var message = "Integration Testing in Microsoft AspNetCore SignalR";
string echo = "";
var hostBuilder = new HostBuilder()
.ConfigureWebHost(webHost => _ = webHost
.UseTestServer()
.UseStartup<Startup>()
.UseEnvironment("IntegrationTest"));
host_?.Dispose();
host_ = await hostBuilder.StartAsync();
TestServer server = host_.GetTestServer();
var connection = new HubConnectionBuilder()
.WithUrl(
"http://localhost:5000/hub/chat?username=21671", options =>
{
options.AccessTokenProvider = () => Task.FromResult("hello");
options.HttpMessageHandlerFactory = _ => server.CreateHandler();
})
.Build();
using IDisposable handler = connection.On<(int, string)>(WebSocketActions.GroupAction, msg =>
{
(_, echo) = msg;
_ = echo.Should().Be("Typing");
});
await connection.StartAsync();
await connection.InvokeAsync("JoinGroup", "group1");
await connection.InvokeAsync("SendToGroup", "group1", 123, "Typing");
_ = echo.Should().Be("Typing");
}
}
Hub.cs
public sealed class ChatHub : Hub
{
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Join a socket group </summary>
///
/// <param name="group"> Identifier for the group. </param>
///
/// <returns> . </returns>
//[Authorize(Policy = "CustomHubAuthorizatioPolicy")]
public async Task JoinGroup(string group)
{
await Groups.AddToGroupAsync(Context.ConnectionId, group);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Send action to group </summary>
///
/// <param name="group"> Identifier for the group. </param>
/// <param name="userId"> Identifier for the user. </param>
/// <param name="action"> Action to send </param>
///
/// <returns> . </returns>
//[Authorize(Policy = "CustomHubAuthorizatioPolicy")]
public async Task SendToGroup(string group, int userId, string action)
{
await Clients.Group(group).SendAsync(WebSocketActions.GroupAction, userId, action);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Leave group </summary>
///
/// <param name="group"> Identifier for the group. </param>
///
/// <returns> . </returns>
//[Authorize(Policy = "CustomHubAuthorizatioPolicy")]
public async Task LeaveGroup(string group)
{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, group);
}
}
The hub works with angular client.
Thanks In Advance.
I have a mvc application. And I am using a API for retrieving. teachers.
This is the class:
[Authorize(Roles = IdentityRoles.Teacher)]
[RoutePrefix("api//current")]
public sealed class CurrentTeacherController : ApiControllerBase
{
private readonly ICurrentTeacherProcess _currentTeacherProcess;
/// <summary>
/// Constructor.
/// </summary>
public CurrentTeacherController(ICurrentTeacherProcess process)
{
_currentTeacherProcess = process;
}
/// <summary>
/// Gets the teacher data of the current user
/// </summary>
/// <returns>The TeacherDto of the current teacher</returns>
[Route("")]
[HttpGet]
public TeacherDto GetTeacher()
{
return _currentTeacherProcess.GetTeacher();
}
}
And I am using Postman for retriving a teacher. For example teacher with id: 1001.
And In Postman I put this:
http://localhost:6598/api/register/
But I get a : 404 not found exception.
This is the startup.cs file:
public sealed class Startup
{
/// <summary>
/// Configures the application for use with OWIN. This method is called implicitly by Microsoft.Owin.Host.SystemWeb.
/// </summary>
/// <param name="app"><see cref="IAppBuilder" />implementation.</param>
public void Configuration(IAppBuilder app)
{
var config = GlobalConfiguration.Configuration;
WebApiConfig.Register(config);
var container = AutofacConfig.Register(config);
app.UseAutofacLifetimeScopeInjector(container);
app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
{
AuthenticationType = "Hallo",
AuthenticationMode = AuthenticationMode.Active,
TokenValidationParameters = ApiGatewaySecurityTokenHandler.CreateTokenValidationParameters(
"hoi", "hoi", IdentityRoles.Duo, IdentityRoles.Competent, IdentityRoles.Berichtenbox),
TokenHandler = container.Resolve<JwtSecurityTokenHandler>()
});
app.UseStageMarker(PipelineStage.PostAuthenticate);
app.UseMiddlewareFromContainer<ApiGatewayMiddleware>();
app.UseAutofacWebApi(config);
app.UseWebApi(config);
}
}
update with startup.cs file
You get a 404 because a handler doesn't exist in your API for that request. You need to add the id to your API route like so
[Route("{id}")]
[HttpGet]
public TeacherDto GetTeacher(int id/* or other type if you aren't using int as your primary key*/ )
{
return _currentTeacherProcess.GetTeacher(id);
}
And your request should be:
http://localhost:6598/api/register/teachers/current/1001
I have a Controller I am using in a Restful API as part of a .NET Core 2 MVC app. I have pasted the code for the controller below.
Everything works great apart form the last method. [HttpDelete("Race/{raceid}")]. When I try and issue a DELETE from Postman or Swagger I get "HTTP verb used to access this page is not allowed"
I can't understand why. My standard Delete method works fine. This is just a second delete method. I have GET methods following a similar pattern and they work fine.
Any ideas?
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using System.Linq;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using System;
using TechsportiseOnline.Data;
using Microsoft.AspNetCore.Identity;
using TechsportiseOnline.Models;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace Techsportise.Controllers
{
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[Route("api/[controller]")]
public class TimingController : Controller
{
private readonly ApplicationDbContext _context;
private readonly UserManager<ApplicationUser> _userManager;
private readonly IAuthorizationService _authorizationService;
public TimingController(ApplicationDbContext context, IAuthorizationService authorizationService,
UserManager<ApplicationUser> userManager)
{
_context = context;
_userManager = userManager;
_authorizationService = authorizationService;
}
/// <summary>
/// Get all Race Timings by Race ID
/// </summary>
/// <remarks>
/// Gets all Race Timings which have been recorded by the user for the passed race
/// </remarks>s
/// <param name="raceid">Race ID</param>
/// <returns>All created Race Timings</returns>
[HttpGet("Race/{raceid}", Name = "GetTimingsByRaceID")]
public IEnumerable<Timing> GetAllByRaceID(long raceid)
{
//Get only records where the OwnerID is not the logged in User.
var alltimings = _context.Timings.Where(p => p.OwnerId == _userManager.GetUserId(User))
.Where(p => p.RaceId == raceid);
return alltimings.ToList();
}
/// <summary>
/// Get Count of Timings by Race ID
/// </summary>
/// <remarks>
/// Gets a count of all Race Timings which have been recorded by the user for the passed race
/// </remarks>s
/// <param name="raceid">Race ID</param>
/// <returns>All created Race Timings</returns>
[HttpGet("Race/{raceid}/count", Name = "GetTimingsCountByRaceID")]
public IActionResult GetCountByRaceID(long raceid)
{
//Get only records where the OwnerID is not the logged in User.
var count = _context.Timings.Where(p => p.OwnerId == _userManager.GetUserId(User))
.Where(p => p.RaceId == raceid)
.Count();
var response = new TimingCount()
{
RaceId = raceid,
TimingsCount = count
};
return new ObjectResult(response);
}
/// <summary>
/// Get a single Race Timing
/// </summary>
/// <remarks>
/// Gets the details from a single Race Timing from it's ID
/// </remarks>
/// <param name="id">Timing ID</param>
/// <returns>Single Race Timing</returns>
[HttpGet("{id}", Name = "GetTiming")]
public IActionResult GetById(long id)
{
var item = _context.Timings .Where(t => t.OwnerId == _userManager.GetUserId(User))
.FirstOrDefault(t => t.Id == id);
if (item == null)
{
return NotFound();
}
return new ObjectResult(item);
}
/// <summary>
/// Create a new Race Timing
/// </summary>
/// <remarks>
/// Creates a new Race Timing
/// </remarks>
/// <returns>The JSON for the created Race Timing</returns>
[HttpPost]
public IActionResult Create([FromBody] TimingPost item)
{
if (item == null)
{
return BadRequest();
}
//Validate that the race ID exists
var race = _context.Races.Where(p => p.OwnerID == _userManager.GetUserId(User)).FirstOrDefault(t => t.ID == item.RaceId);
if (race == null)
{
return BadRequest("The RaceID you have sent does not exist");
}
var timingitem = new Timing();
timingitem.EndTime = item.EndTime;
timingitem.RaceId = item.RaceId;
timingitem.OwnerId = _userManager.GetUserId(User);
timingitem.Position = item.Position;
timingitem.StartTime = item.StartTime;
timingitem.LastUpdated = DateTime.Now;
_context.Timings.Add(timingitem);
_context.SaveChanges();
return CreatedAtRoute("GetTiming", new { id = timingitem.Id }, timingitem);
}
/// <summary>
/// Update a Race Timing
/// </summary>
/// <remarks>
/// Update's a Race Timing's details
/// </remarks>
/// <param name="id">Timing ID</param>
/// <returns>The JSON for the updated Race Timing</returns>
[HttpPut("{id}")]
public IActionResult Update(long id, [FromBody] Timing item)
{
if (item == null)
{
return BadRequest();
}
//Validate that the race ID exists
var race = _context.Races.Where(p => p.OwnerID == _userManager.GetUserId(User)).FirstOrDefault(t => t.ID == item.RaceId);
if (race == null)
{
return BadRequest("The RaceID you have sent does not exist");
}
var timing = _context.Timings .Where(t => t.OwnerId == _userManager.GetUserId(User))
.FirstOrDefault(t => t.Id == id);
if (timing == null)
{
return NotFound();
}
timing.RaceId = item.RaceId;
timing.StartTime = item.StartTime;
timing.EndTime = item.EndTime;
timing.Position = item.Position;
timing.OwnerId = _userManager.GetUserId(User);
timing.LastUpdated = DateTime.Now;
_context.Timings.Update(timing);
_context.SaveChanges();
return new NoContentResult();
}
/// <summary>
/// Delete a Race Timing
/// </summary>
/// <remarks>
/// Deletes a Race Timing. Note: This will orphan any related result data and is not recommended!
/// </remarks>
/// <param name="id">Race Entry ID</param>
/// <returns></returns>
[HttpDelete("{id}")]
public IActionResult Delete(long id)
{
var timing = _context.Timings .Where(t => t.OwnerId == _userManager.GetUserId(User))
.FirstOrDefault(t => t.Id == id);
if (timing == null)
{
return NotFound();
}
_context.Timings.Remove(timing);
_context.SaveChanges();
return new NoContentResult();
}
/// <summary>
/// Delete all timings for a Race
/// </summary>
/// <remarks>
/// Deletes all timings for the race passed
/// </remarks>
/// <param name="raceid">Race ID</param>
/// <returns></returns>
[HttpDelete("Race/{raceid}")]
public IActionResult DeleteAllTimingsForRace(long raceid)
{
var race = _context.Races.Where(t => t.OwnerID == _userManager.GetUserId(User))
.FirstOrDefault(t => t.ID == raceid);
if (race == null)
{
return NotFound();
}
if ((race.ResultStatus == "Published") || (race.ResultStatus == "Provisional"))
{
return BadRequest("You cannot delete scans for a race which is already published");
}
foreach (var timing in _context.Timings.Where(p => p.OwnerId == _userManager.GetUserId(User))
.Where(p => p.RaceId == raceid))
{
_context.Timings.Remove(timing);
}
_context.SaveChanges();
return new NoContentResult();
}
}
}
This actually ended up being a server configuration relating to WebDAV.
I ended up testing on 3 local environments with no issues so isolated it to the server, then did some more forensic searching narrowed it down to disabling WebDAV in my Web.Config on the dpeloyed server.
<modules runAllManagedModulesForAllRequests="false">
<remove name="WebDAVModule" />
</modules>
Yesterday I coded myself a simple RESTful web API in .NET Core (solution named Vault) with a single method that gets the profile of the user depending only on the Windows user name. I now have a second solution that will call some requests to my self-hosting service previously mentioned. When I use Postman, I can retrieve the data with ease when I call a GET on my only method in Vault, but when I build the URI in Mainframe and execute, I get an Unauthorized error and it confuses me as Vault does not require specific login like username and password. I also put a breakpoint in Vault and unlike when I'm using Postman, it does not reach my code when calling via the Mainframe solution.
Here where is build my REST request and call the service (GetProfile())
public VaultApiClient(ConfigurationManagerWrap configuration)
{
this.configuration = configuration;
this.client = new RestClient(new Uri(this.configuration.GetAppSetting<string>(ConfigurationKeys.VaultApiURL)));
}
/// <summary>
/// The get profile.
/// </summary>
/// <returns>
/// The <see cref="UserProfile"/>.
/// </returns>
public UserProfile GetProfile()
{
var request = new RestRequest("profile") { Method = Method.GET};
//request.AddParameter("profile", ParameterType.UrlSegment);
var response = this.client.Execute(request);
if (response.StatusCode != HttpStatusCode.OK)
{
throw new Exception(
$"Could not get the user profile ({response.StatusCode} {response.StatusDescription})");
}
return RestJsonSerializer.Default.Deserialize<UserProfile>(response);
}
Im hosting local so the base URI, aka ConfigurationKeys.VaultApiURL, is localhost5000/api/
My Mainframe controller :
public HomeController()
: this(new VaultApiClient(new ConfigurationManagerWrap()))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="HomeController"/> class.
/// </summary>
/// <param name="vaultApiClient">
/// The vault api client.
/// </param>
public HomeController(IVaultApiClient vaultApiClient)
{
this.vaultApiClient = vaultApiClient;
}
/// <summary>
/// The index.
/// </summary>
/// <returns>
/// The <see cref="ActionResult"/>.
/// </returns>
public ActionResult Index()
{
var profile = this.GetProfile();
this.ViewBag.IsEdit = false;
this.ViewBag.IsError = false;
this.ViewBag.ErrorMessage = "";
if (this.TempData.ContainsKey("IsEdit"))
{
this.ViewBag.IsEdit = true;
this.TempData.Remove("IsEdit");
if (this.TempData.ContainsKey("ErrorMessage"))
{
this.ViewBag.IsError = true;
this.ViewBag.ErrorMessage = this.TempData["ErrorMessage"];
this.TempData.Remove("ErrorMessage");
}
}
return this.View("Index", profile);
}
private UserProfile GetProfile()
{
return this.vaultApiClient.GetProfile();
}
And here is the vault controller method that handles the GET request in question:
[HttpGet]
[Route("/api/Profile")]
[Produces(typeof(UserProfile))]
public IActionResult SearchProfile()
{
try
{
if (!this.currentuser.IsAuthenticated)
{
throw new Exception("This service does not support anonymous calls.");
}
var profile = Task.Run(() => this.personalizationService.GetUserProfileAsync(this.currentuser.GetCurrentWindowsIdentityName)).Result;
var userProfile = this.persistenceToDataModelConverter.Convert(profile);
userProfile.UserAdLogin = this.currentuser.GetCurrentWindowsIdentityName;
return this.Ok(userProfile);
}
catch (Exception ex)
{
return this.NotFound(ex);
}
}
Lastly, here are a few pics of before and when the error is thrown.
Credential information must be provided with client request in order to authenticate with the server.