I just don't understand what I have to set as the service name for the EntityManager.
I hava two controllers: an ApiController and a 'normal' controller:
API Controller:
[BreezeController]
public class TournamentApiController : ApiController
{
private EFContextProvider<TournamentContext> _contextProvider;
public TournamentApiController()
{
_contextProvider = new EFContextProvider<TournamentContext>();
}
[HttpGet]
public string Metadata()
{
return _contextProvider.Metadata();
}
[HttpGet]
public IQueryable<Tournament> Tournaments()
{
return _contextProvider.Context.Tournaments;
}
[HttpGet]
public IQueryable<Team> Teams()
{
return _contextProvider.Context.Teams;
}
}
'Normal' controller:
public class TournamentController : Controller
{
public ActionResult Index()
{
return PartialView();
}
public ActionResult Details()
{
return PartialView();
}
}
And in my DataSrvice.js file:
app.dataservice = (function (breeze) {
breeze.config.initializeAdapterInstance("modelLibrary", "backingStore", true);
var serviceName = '/TournamentApi'; // What exactly do I need to set here?
// *** Cross origin service example ***
//var serviceName = 'http://todo.breezejs.com/breeze/todos'; // controller in different origin
var manager = new breeze.EntityManager(serviceName);
// manager.enableSaveQueuing(true);
var dataservice = {
getAllTournaments: getAllTournaments,
};
return dataservice;
/*** implementation details ***/
function getAllTournaments() {
var query = breeze.EntityQuery
.from("Tournament");
return manager.executeQuery(query);
}
})(breeze);
Can someone explain what is meant by a service name and thus, what I should use as the service name?
The serviceName identifies the service end-point, the route to the Web API controller. This will be the "root" of the URL you use to communicate with the server. So if the actual endpoints to query 'teams' and 'tournaments' are
http://foo/bar/tournamentApp/teams ...
http://foo/bar/tournamentApp/tournaments ...
then your service name will be
"foo/bar/tournamentApp"
Related
how can i fix this error
An unhandled exception occurred while processing the request.
AmbiguousMatchException: The request matched multiple endpoints. Matches:
CoreDemo.Areas.Admin.Controllers.HomeController.Index (CoreDemo)
CoreDemo.Controllers.HomeController.Index (CoreDemo)
namespace CoreDemo.Controllers
{
public class HomeController : Controller
{
private readonly ILogger _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
return View();
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
public IActionResult Test()
{
return View();
}
}
}
/////////////////////////////////////////////////////////////////////////////////////
namespace CoreDemo.Areas.Admin.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
}
The problem is that you register to controllers with the same name (HomeController) without defining a custom Route then .net doesn't know which to pick.
You can give your controllers custom routes by using the Route attribute see docs here: https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-7.0#attribute-routing-with-http-verb-attributes
So you can add the Route attribute like this to your code:
namespace CoreDemo.Areas.Admin.Controllers
{
[Route("admin/[controller]/[action]")]
public class HomeController : Controller
{
public IActionResult Index()
{
return ControllerContext.MyDisplayRouteInfo();
}
}
}
namespace CoreDemo.Controllers
{
[Route("[controller]/[action]")]
public class HomeController : Controller
{
private readonly ILogger _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
return View();
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
public IActionResult Test()
{
return View();
}
}
}
I have the following issue. Whenever I send something to my Api endpoint, ASP.NET Core 3.1 is not able to process the request. However, when I add the ApiController attribute it works perfectly fine.
My code is correct but only works when I add this attribute. How is that so?
For reference, here's my code
API
[ApiController] //Remove this and the code breaks
[Route("api/SomeApi")]
public class ApiController : Controller {
private readonly IService service;
public ApiController(IService service)
{
this.service = service;
}
[HttpPost]
[Route("Add")]
public SomeClass Add(SomeClass foo)
{
var userId = service.GetCurrentUserId(User);
foo.Id = Guid.NewGuid();
foo.UserId = userId;
service.Add(foo);
return foo;
}
}
JS
axios.post('/api/SomeApi/Add', {
foo: this.foo,
}).then(function (response: any) {
this.Id = response.Id;
});
FYI, I have other methods on my ApiController using GET/POST. The GET ones work perfectly fine but the POST methods only work when I use query parameters. In this case, I didn't use query parameters because I have more data to send to my Api than actually given in the example.
I've already tried to get my response using [FromBody]. It did not work. I instead got null. foo was not even instantiated.
For binding request body to model, there are two types, one is binding from form data and the other is application/json.
For Controller,it would fetch the form data by default.For ApiController,it would fetch the json data by default.
If you want bind request body without using [ApiController],you could add [FromBody]:
//[ApiController]
[Route("api/SomeApi")]
public class ApiController : Controller
{
private readonly IService service;
public ApiController(IService service)
{
this.service = service;
}
[HttpPost]
[Route("Add")]
public SomeClass Add([FromBody]SomeClass foo)
{
//do your stuff...
}
}
Model:
public class SomeClass
{
public int Id { get; set; }
public string Name { get; set; }
}
View:
#section Scripts{
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
axios.post('/api/SomeApi/Add', {
id: 1,
name: 'sdfsdf'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
</script>
}
Result:
I had the same problem and solved it using qs library for stringifying the JSON Object.
axios.post('/controller/action', Qs.stringify({Id: 1, Name: 'Test'}))
.then(function (response) {
console.log(response);
})
.catch(function (response) {
console.log(response);
});
Another way that worked for plain objects is using URLSearchParams.
var requestData = {Id: 1, Name: 'Test'}
var params = new URLSearchParams();
for(key in requestData)
params.append(key, requestData[key]);
axios.post('/controller/action', params)
.then(function (response) {
console.log(response);
})
.catch(function (response) {
console.log(response);
});
We are trying to implement a custom service using aspnetboilerplate .NET Core Multi Page Application template. We are receiving an error in index.js file when trying to hit a service method.
Find herewith the code sections for understanding. Any help on this will be really helpful for us.
public interface IMyTaskAppService : IApplicationService
{
Task<List<string>> GetMyTasks(int input);
}
public class MyTaskAppService : IMyTaskAppService
{
private readonly IMyTaskRepository _mytaskRepository;
public MyTaskAppService(IMyTaskRepository mytaskRepository)
{
_mytaskRepository = mytaskRepository;
}
Task<List<string>> IMyTaskAppService.GetMyTasks(int input)
{
return _mytaskRepository.GetMyTasks(input);
}
}
Index.Js
Index.Js Error (Lowercase)
Console Output Screenshot
MyTaskAppService requires at least one public method:
public class MyTaskAppService : IMyTaskAppService
{
// ...
// Task<List<string>> IMyTaskAppService.GetMyTasks(int input)
public Task<List<string>> GetMyTasks(int input)
{
return null;
}
}
What you have is an explicit implementation that is "more restricted than private".
Service and method names are in camelCase for Client Proxies.
Use an uppercase T for myTask:
var _myTaskService = abp.services.app.myTask;
Use a lowercase g for getMyTasks:
_myTaskService.getMyTasks({
taskID: taskID
}).done(function (data) {
alert(data);
});
Add ApplicationService as a base for your MyTaskAppService class.
See my code;
public class MyTaskAppService : ApplicationService, IMyTaskAppService
{
private readonly IMyTaskRepository _mytaskRepository;
public MyTaskAppService(IMyTaskRepository mytaskRepository)
{
_mytaskRepository = mytaskRepository;
}
Task<List<string>> IMyTaskAppService.GetMyTasks(int input)
{
return _mytaskRepository.GetMyTasks(input);
}
}
See TaskAppService.
public interface IMyTaskAppService : IApplicationService
{
Task<List<string>> GetMyTasks(int input);
}
See the complete source-code of SimpleTaskSystem
Below is my Angular js Front end Code
app.controller("assetController", ['$scope', '$http', function ($scope, $http) {
$scope.submit = function () {
var book = {
"Name": $scope.name,
"Isbn": $scope.isbn,
"Publisher": $scope.publisher,
"Edition":$scope.edition
}
$http.post("http://localhost:51227/api/Asset", book)
.then(function(data, status) {
$scope.name = book.Name;
$scope.isbn = book.Isbn;
$scope.publisher = book.Publisher;
$scope.edition=book.Edition;
alert("product added successfully. " + status);
})
.catch(function(response) {
console.log('Exception Caught', response.status, response.data);
})
.finally(function() {
});
}
This is my webApi Controller
public void Post([FromBody] AssetViewModel model)
{
if ( model is BookViewModel)
{
BookViewModel bookViewModel = (BookViewModel)model;
AssetViewModel assetViewModel = new BookViewModel
{
Name = bookViewModel.Name,
Category = bookViewModel.Category,
Edition = bookViewModel.Edition,
Isbn = bookViewModel.Isbn,
Publisher = bookViewModel.Publisher
};
_assetAssetRepository.SaveAsset(Mapper.Map<Book>(assetViewModel));
}
}
Below are the Two ViewModel Classes
public class AssetViewModel
{
public string Name { get; set; }
}
public class BookViewModel:AssetViewModel
{
public string Isbn { get; set; }
public string Edition { get; set; }
public string Publisher { get; set; }
public string Category { get; set; }
}
So basically this is a simple Angular js Code that makes a call to WebAPI Controller and passes Book Object ( or the BookViewModel). The Parameter for the WebApi is AssetViewModel (BaseClass) but its ok because we should be able to pass in BookViewModel(Derived Class) at runtime. The Angular Front End passes Book Object but when i check in the webapi controller it shows up as a parent class i.e. Asset. Therefore i cannot retrive the fields associated with Book Class. Could someone please show me the right way?
How can I pass JsonResult object from javascript function in View to Controller Action without Ajax call - just javascript - window.location.href = url?
I get JsonResult object from Controller Action to javascript function via Ajax call. Then I want to pass this object back to other Controller Action but I get object with null reference properties.
My javascript function in View:
function order(model) {
$('#details-container').html("<h2>Loading Complete Frame Module. Please wait...</h2>");
$.p({
url: '#Url.Action("CompleteFrameBrandDetails", "PacCompleteFrame")',
data: { item: model },
success: function (xml) {
if (xml.Success) {
$.p({
url: '#Url.Action("GlassCompleteFrame", "PacModule")',
data: JSON.stringify({ b2bXml: xml.Data }),
success: function (model) {
var pacModuleModel = {
Mode: model.Data.Mode,
IframeUrl: model.Data.IframeUrl.toString(),
CustomerNumber: model.Data.CustomerNumber.toString(),
ReadOnly: model.Data.ReadOnly,
GlassXml: model.Data.GlassXml.toString(),
Price: parseFloat(model.Data.Price),
Comission: model.Data.Comission.toString(),
Permissions: null,
Language: model.Data.Language.toString()
};
// here are all values in model.Data correct
// but then I can't figure out how to pass it to Controller Action without Ajax call - just with javascript command
var url = '#Url.Action("GlassCompleteFrameView", "PacModule", "__view__")';
window.location.href = url.replace("__view__", model.Data); //pacModuleModel
}
});
} else {
$.alert({
message: 'error while trying to load xml details'
});
}
}
});
}
My Controller Action:
public ActionResult GlassCompleteFrameView(PacModuleModel model)
{
// here I get object module but
// model.CustomerNumber = null
// model.GlasXml = null
// model.Price = null
// ...
return View("Glass", model);
}
I have also Model like this for automatic Json binding but dont work:
public enum ModuleMode
{
ByProduct,
ByRecipe
}
public partial class PacModuleModel
{
private PacPermissionModel permissionModel;
public ModuleMode Mode { get; set; }
public string IframeUrl { get; set; }
public string CustomerNumber { get; set; }
public bool ReadOnly { get; set; }
public string GlassXml { get; set; }
public double? Price { get; set; }
public string Comission { get; set; }
public PacPermissionModel Permissions
{
get
{
if (permissionModel == null)
{
permissionModel = new PacPermissionModel();
}
return permissionModel;
}
}
public string Language { get; set; }
}
Try this in controller
public JsonResult GlassCompleteFrameView(PacModuleModel model)
{
// here I get object module but
// model.CustomerNumber = null
// model.GlasXml = null
// model.Price = null
// ...
return Json(model, JsonRequestBehavior.AllowGet);
}
The problem was in model. It was more than 45000 char long. Now I use Session variable to get model in GlassCompleteFrameView(PacModuleModel model) and works perfect.
public ActionResult GlassCompleteFrameView(PacModuleModel model)
{
model = Session["xml"] as PacModuleModel;
return View("Glass", model);
}