I have this API methods:
namespace Playground.Web.Controllers.API
{
public class FilterConfigurationsController : ApiController
{
private readonly PlaygroundContext _context;
public FilterConfigurationsController()
{
_context = new PlaygroundContext();
}
[HttpPost]
public async Task<IHttpActionResult> Post(Filter data)
{
try
{
var ere = FilterViewModel.GenerateDataForFilters(data, _context);
return Ok(data);
}
catch (Exception ex)
{
throw;
}
}
[HttpPost]
public async Task<IHttpActionResult> Post(IEnumarable<Filter> filterDescriptionList)
{
try
{
var data = FilterViewModel.GenerateDataForFilters(filterDescriptionList, _context);
return Ok();
}
catch (Exception ex)
{
throw;
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_context.Dispose();
}
base.Dispose(disposing);
}
}
}
To call this methods I use this HTTP post calls:
$http.post(config.baseUrl + "api/FilterConfigurations/", scope.filterParams).then(function (result) {});
I am working on web API project and using AngularJS in my project.
This HTTP post call:
$http.get(config.baseUrl + "api/FilterConfigurations/,{data= scope.filterParams[0]}).then(function (result) {});
have to call this method API:
public async Task Post(Filter data)en(function (result) {});
But the method API above never fired.
Instead this method alwaes fired:
public async Task<IHttpActionResult> Post(Filter filterDescriptionList)
Any idea why the API method never fired?
What I am doing wrong?
Related
console error is
ERR_CONNECTION_REFUSED and Uncaught (in promise) AxiosError {message: 'Network Error', name: 'AxiosError', code: 'ERR_NETWORK' ~
like this:
controller
[ApiController]
[Route("api/[controller]")]
public class AccountController : ControllerBase
{
private readonly IHaruUserRepository _repository;
private readonly ILogger _logger;
public AccountController(IHaruUserRepository repository, ILoggerFactory loggerFactory)
{
this._repository = repository ?? throw new ArgumentNullException(nameof(AccountController));
this._logger = loggerFactory.CreateLogger(nameof(AccountController));
}
[HttpGet] // [HttpGet("[action]")]
public async Task<IActionResult> GetAll()
{
try
{
var models = await _repository.GetAllAsync();
if (!models.Any())
{
return new NoContentResult();
}
return Ok(models);
}
catch (Exception e)
{
_logger.LogError(e.Message);
return BadRequest();
}
}
function
async handleSubmit(e) {
e.preventDefault();
await axios.get("/api/account").then(result => {
});
}
I added 'services.AddTransient<'interface name of repository', 'repository name'>();' in DI Container.
I was trying to get specific data from database but every time I'm getting the following error!
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to com.lglsys.entity.TDasProductDownload
So this is my QueryService class
#Dependent
public class QueryService {
List<TDasProductDownload> downloadLink = new ArrayList();
final private Logger logger =
LogManager.getLogger(QueryService.class.getName());
#PersistenceContext(unitName="DownloadServices")
EntityManager em;
public QueryService() { super(); }
public List<TDasProductDownload> findAllDownloadLinks() {
try {
downloadLink=
em.createQuery(queryForDownloadLinks,TDasProductDownload.class)
.getResultList();
return downloadLink;
} catch (Exception e) {
logger.info(e.toString());
return null;
}
}
}
program gives error in this class /
EndPoint class
public class PreControlWSEndPoint {
private Session session;
final private Logger logger = LogManager.getLogger(PreControlWSEndPoint.class.getName());
List<TDasProductDownload> downloadLink = new ArrayList();
#PersistenceContext(unitName="DownloadServices")
EntityManager em;
#Inject
QueryService service;
#OnOpen
public void Open(Session session) throws IOException, InterruptedException {
this.session = session;
this.sendMessage("Connection Oppened");
logger.info("EndPoint Opened");
try {
downloadLink = service.findAllDownloadLinks();
logger.info(downloadLink.size());
TDasProductDownload str = downloadLink.get(0);
logger.info(str.getDownloadStatus()); //**Eror line!!**
} catch (Exception e) {
logger.info(e.toString() + " .D");
}
}
#OnMessage
public void onMessage(String message) {}
#OnClose
public void Close() {}
}
I can't see what's happening in my code.
I fixed it!
public List<String> findAllDownloadLinks() {
try {
downloadLink=
em.createQuery(queryForDownloadLinks,String.class)
.getResultList();
return downloadLink;
} catch (Exception e) {
logger.info(e.toString());
return null;
}
}
then i can print like so
for(int temp=0;temp<=downloadLink.size();temp++){
logger.info(downloadLink.get(temp));
}
I have the following API, which takes care of updating items in the database:
[Route("update")]
[HttpPost("")]
public JsonResult UpdateRecords([FromBody]ICollection<ShoppingItemViewModel> vm)
{
if (ModelState.IsValid)
{
try
{
var items = Mapper.Map<IEnumerable<ShoppingItem>>(vm);
//update database
_repository.UpdateValues(items, User.Identity.Name);
return Json(null);
}
catch (Exception Ex)
{
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(null);
}
}
else
{
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(null);
}
}
Then under my Angular code I am executing this POST method like following:
$scope.SaveChanges = function () {
$http.post("/api/items/update", $scope.items)
.then(function (response) {
}, function (err) {
$scope.errorMessage = "Error occured: " + err;
}).finally(function () {
});
};
What I would like to do, is to introduce new parameters to my initial UpdateRecords function, where some of them are optional. Then depending on the inserted parameters my procedure would do different things.
What I have tried to do is to change my function like following (example):
public JsonResult UpdateRecords([FromBody]ICollection<ShoppingItemViewModel> vm, [FromBody]bool EraseOldItems)
and under my Angular App:
$http.post("/api/items/update", {vm:$scope.items, EraseOldItems: true})
or even
$http.post("/api/items/update", {'vm':$scope.items, 'EraseOldItems': true})
but I could not get the code to work (my parameters were all the time null).
What am I doing wrong here?
From Parameter Binding in ASP.NET Web API:
At most one parameter is allowed to read from the message body.
// Caution: Will not work!
public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }
The reason for this rule is that the request body might be stored in a
non-buffered stream that can only be read once.
You can pass a request object that contains other objects:
public class Request
{
public ICollection<ShoppingItemViewModel> vm { get; set; }
public bool eraseOldItems { get; set; }
}
And then your action:
[Route("update")]
[HttpPost("")]
public JsonResult UpdateRecords([FromBody]Request request){ ... }
Here is my web api controller:
[HttpGet]
public HttpResponseMessage SensorData(string id)
{
try
{
Responds data = AccessRemote.GetDataFromDevice(id);
DataResponds dataResponds = data.ReturnDatRequest[0];
return Request.CreateResponse(HttpStatusCode.OK, dataResponds);
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.Forbidden, ex.Message);
}
}
[HttpGet]
public HttpResponseMessage GetLogs(string GetRecordsById)
{
try
{
IQueryable<SensorInfo> data = sensorResultsRepos.Get();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, data);
return response;
}
catch (Exception)
{
throw;
}
}
Here is my resource angularjs definition:
(function () {
"use strict";
angular.module("sensorManagement").factory("SensorResource",
["$resource",
SensorResource])
function SensorResource($resource) {
return $resource("http://localhost:1234/api/SomeData/:id");
}
}());
Here is web api route:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
"DefaultApiSensor",
"api/{controller}/{id}",
new { controller = "Sensor", id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
At some point I need to access to SensorData action or to GetLogs action using the SensorResource service.
The problem that they are both HTTP GET and both have one parameter.
How can I make call to SensorData and to GetLogs if they in one controller and the have sane http get type?
You can use Attribute Routing to easily solve this problem. See this link for more information regarding this topic.
[HttpGet]
[Route("sensor/{id}")]
public HttpResponseMessage SensorData(string id)
{
try
{
Responds data = AccessRemote.GetDataFromDevice(id);
DataResponds dataResponds = data.ReturnDatRequest[0];
return Request.CreateResponse(HttpStatusCode.OK, dataResponds);
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.Forbidden, ex.Message);
}
}
[HttpGet]
[Route("logs/{GetRecordsById}")]
public HttpResponseMessage GetLogs(string GetRecordsById)
{
try
{
IQueryable<SensorInfo> data = sensorResultsRepos.Get();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, data);
return response;
}
catch (Exception)
{
throw;
}
}
I am trying to call a WCF service from a Silverlight client using channel factory as per this link. Working with channel factory is something new for me so please bear with me!
Everything mentioned in the article works just fine. But now I am trying to implement Fault exceptions so that I can catch the actual exceptions on the Silverlight side. But for some reason I always end up catching CommunicationException which doesn't serve my purpose.
Here is my service contract:
[OperationContract]
[FaultContract(typeof(Fault))]
IList<Category> GetCategories();
Catch block of the service:
catch (Exception ex)
{
Fault fault = new Fault(ex.Message);
throw new FaultException<Fault>(fault, "Error occured in the GetCategories service");
}
Service contract for client with async pattern:
[OperationContract(AsyncPattern = true)]
[FaultContract(typeof(Fault))]
IAsyncResult BeginGetCategories(AsyncCallback callback, object state);
IList<Category> EndGetCategories(IAsyncResult result);
Here is the service call from client:
ICommonServices channel = ChannelProviderFactory.CreateFactory<ICommonServices>(COMMONSERVICE_URL, false);
var result = channel.BeginGetCategories(
(asyncResult) =>
{
try
{
var returnval = channel.EndGetCategories(asyncResult);
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
CategoryCollection = new ObservableCollection<Category>(returnval);
});
}
catch (FaultException<Fault> serviceFault)
{
MessageBox.Show(serviceFault.Message);
}
catch (CommunicationException cex)
{
MessageBox.Show("Unknown Communications exception occured.");
}
}, null
);
I am sharing the DataContract .dll between both the service and client applications and hence they are referring to same data contract classes (Category & Fault)
Please tell me what I am doing wrongly?
UPDATE: I do clearly see the fault exception sent from the service in Fiddler. Which makes me believe I am missing something in the client side.
For catching normal exceptions in sivleright you must create "Silverlight-enabled WCF Service" (Add -> New Item -> Silverlight-enabled WCF Service).
If you already created standard WCF service you can add attribute [SilverlightFaultBehavior] to your service manually.
Default implementation of this attribute is:
public class SilverlightFaultBehavior : Attribute, IServiceBehavior
{
private class SilverlightFaultEndpointBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new SilverlightFaultMessageInspector());
}
public void Validate(ServiceEndpoint endpoint)
{
}
private class SilverlightFaultMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
if ((reply != null) && reply.IsFault)
{
HttpResponseMessageProperty property = new HttpResponseMessageProperty();
property.StatusCode = HttpStatusCode.OK;
reply.Properties[HttpResponseMessageProperty.Name] = property;
}
}
}
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints)
{
endpoint.Behaviors.Add(new SilverlightFaultEndpointBehavior());
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
}
We use our own custom ServiceException class on the server e.g.
[Serializable]
public class ServiceException : Exception
{
public ServiceException()
{
}
public ServiceException(string message, Exception innerException)
: base(message, innerException)
{
}
public ServiceException(Exception innerException)
: base("Service Exception Occurred", innerException)
{
}
public ServiceException(string message)
: base(message)
{
}
}
And then in our server side service methods we use error handling like this:
try
{
......
}
catch (Exception ex)
{
Logger.GetLog(Logger.ServiceLog).Error("MyErrorMessage", ex);
throw new ServiceException("MyErrorMessage", ex);
}
We then use a generic method for all web service calls:
/// <summary>
/// Runs the given functon in a try catch block to wrap service exception.
/// Returns the result of the function.
/// </summary>
/// <param name="action">function to run</param>
/// <typeparam name="T">Return type of the function.</typeparam>
/// <returns>The result of the function</returns>
protected T Run<T>(Func<T> action)
{
try
{
return action();
}
catch (ServiceException ex)
{
ServiceLogger.Error(ex);
throw new FaultException(ex.Message, new FaultCode("ServiceError"));
}
catch (Exception ex)
{
ServiceLogger.Error(ex);
throw new FaultException(GenericErrorMessage, new FaultCode("ServiceError"));
}
}