How to convert url.HttpRouteUrl to a normal string url? - c#

I inherited some code and I am trying to figure the right url to a webapi controller but my knowledge of mvc web api is lacking.
I have inline script that is making an ajax post like this:
$('#saveNewEducation').on('click', function () {
var educationAdd = {
'educationId': $('#newEducation').val(),
'startDate': $('#newEducationDate').val(),
'identificationId': $('#identificationId').val(),
'educationNote': $('#newEducationNote').val(),
'examinerId': $('#newExaminer').val()
};
$.post('#Url.HttpRouteUrl("DefaultApi", new { controller = "EmployeeApi", educationName = "educationCreate" })', educationAdd)
.done(function (data, textStatus, jqXhr) {
if (jqXhr.status == 200) {
$('#save-education').modal('show');
} else {
$('#fail-save-employee').modal('show');
}
})
.fail(function (jqXhr) {
var education = $("#new-education");
if (jqXhr.status == 409) {
$('#future-save-employee').modal('show');
} else {
if (jqXhr.status == 400) {
clearErrors(education);
var validationErrors = $.parseJSON(jqXhr.responseText);
$.each(validationErrors.ModelState, function (i, ival) {
remoteErrors(education, i, ival);
});
} else {
$('fail-save-employee').modal('show');
}
}
});
I don't like inline script and I have created a seperate js file where I want to make this call from.
I need help with
I need help figuring out the right url to the api controller so that i can use it in the script file.
I tried
Reading this article I tried the following:
$.post('/DefaultApi/EmployeeApi', educationAdd)
This gave me a
404 not found error.
in the inline script the url is like this:
$.post('#Url.HttpRouteUrl("DefaultApi", new { controller = "EmployeeApi", educationName = "educationCreate" })', educationAdd)
WebApiConfig.cs file:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional });
method I am trying to access in EmployeeApi controller:
public IHttpActionResult EducationPost(EmployeeEducation model, string educationName){}
How can I do this?

Resolving the URL
Generally in MVC applications, you would resolve this by using the Url.Action() helper to resolve the proper URL provided its Controller, Action and RouteValues:
// Supply the Action, Controller and any route values that you need
$.post('#Url.Action("EducationPost","EmployeeApi", new { educationName = "educationCreate"})', function(){
// Do something here
});
However, Web API also features the Url.Link() helper that might be useful as well and works in a similar manner except based on the route itself :
$.post('#Url.Link("DefaultApi", new { controller = "EmployeeApi", action = "EductationPost", educationName = "educationCreate" })', function(){
// Do something here
});
When using External Javascript Files
As you would imagine, these techniques won't work when using external Javascript files. What I generally recommend in these situations is to consider using a data-* attribute in HTML to store the URL and then reference that within your event handler that will trigger the AJAX call :
<button id='call-ajax' data-post-url='#Url.Action(...)' />
<script>
$(function(){
$('#call-ajax').click(function(e){
// Read the attribute and use it
$.post($(this).attr('data-post-url'), function(){
// All done
});
});
});
</script>
You could obviously accomplish this same basic idea through the use of variables or hidden elements, but the same idea basically holds true as far as actually accessing it goes.

Have a look at this answer:
How to send razor created Url to js file
This user offers 3 possible solutions.
global js variable
custom "data-" attribute
hidden input

Related

How to pass jQuery variable value to c# mvc?

How to pass jQuery variable value to c# mvc ?
I need to fetch the value of the variable btn in mvc code behind.
$('button').click(function () {
var btn = $(this).attr('id');
alert(btn);
$.ajax({
type: 'GET',
url: '#Url.Action("ActionName", "ControllerName")',
data: { id: btn },
success: function (result) {
// do something
}
});
});
Based on the variable value (Submit Button (or) Preview Button), my model will have Required validation on certain fields.
In my controller , i am calling as
[HttpGet]
public ActionResult ActionName(string id)
{
var vm = id;
return View(vm);
}
Though , ActionResult in controller is not invoked.
Jquery : alert(btn); -- is calling. I can see the alert window showing with the id. However, I am not able to retrieve the id in the controller.
You need to use jQuery.ajax() (or its shortened form jQuery.get()/jQuery.post()) with GET/POST method and set up a controller action with an argument to pass button ID:
jQuery (inside $(document).ready())
$('button').click(function () {
var btn = $(this).attr('id');
var url = '#Url.Action("ActionName", "ControllerName")';
var data = { id: btn };
// if controller method marked as POST, you need to use '$.post()'
$.get(url, data, function (result) {
// do something
if (result.status == "success") {
window.location = '#Url.Action("AnotherAction", "AnotherController")';
}
});
});
Controller action
[HttpGet]
public ActionResult ActionName(string id)
{
// do something
return Json(new { status = "success", buttonID = id }, JsonRequestBehavior.AllowGet);
}
[HttpGet]
public ActionResult AnotherAction()
{
// do something
return View(model);
}
If you want to pass retrieved button ID from AJAX into other action method, you can utilize TempData or Session to do that.
It is a nice coincidence that you use the word "fetch" to describe what you want to do.
jQuery runs in the browser as a frontend framework. Meaning that it runs on the client`s computer. Your MVC-C#-Code lies on the server. Therefore, if you want to send data between those two computers, you need to use the http protocol.
1. Ajax and REST:
Using an ajax call using http methods (post or put) to push your variable value as JSON to the backend`s REST api (route).
For this option, you might want to have a look at the fetch function of javascript.
2. HTML Forms
Use a html form where you store the variable value inside one input element. A form submission will perform a http post (by default) request to the backend as well and use all input element values as post parameters.
There are many ways to accomplish what you are looking to do, but I'll stick to using your code sample.
So what you need to do is utilize the .ajax call in jquery to send data from your view to your controller. More on that here: http://api.jquery.com/jquery.ajax/
Using your code, you'd put the .ajax call within your logic flow of what to do based on which button is clicked.
$("button").click(function ()
{
var btn = this.id;
if (btn == "previewButton")
{
$.ajax({
url: "/MyApp/MyAction",
type: "POST",
data: { btnId: btn },
dataType: "json",
async: true,
cache: false
}).success(function(data){
// do something here to validate if your handling worked
}).error(function(){
// Do something here if it doesnt work
});
}
}
You'll see that there is a URL. In my example i've chose MyApp as my controller and MyAction as the method of the controller in which we are posting values to. The ajax call posts 1 parameter with a property of btnId. If you need to pass more data, the property name in the jquery call should correspond with an argument of the actions method signature within the controller.
So my controller looks like
public MyAppController : Controller
{
[HttpPost]
public JsonResult MyAction(string btnId)
{
Debug.WriteLine("btnId: {0}", btnId);
return Json(new{ ButtonId= btnId });
}
}
This would be one way to handle passing values from your view to your controller using .ajax calls with jquery.
My preferred way is to use the Html helpers of Ajax.BeginForm which could be another option for you.
https://www.aspsnippets.com/Articles/ASPNet-MVC-AjaxBeginForm-Tutorial-with-example.aspx

How to send 2 parameters i angularjs to mvc controller?

I have a post method in my js file which need to send 2 parameters.
var patientData = { 'clinicalRegistryPatient': $scope.patientFile,'emailDetails': $scope.patientFile.emailDetails };
Service.post(Service.API.REGISTER_PATIENT, patientData).then(function success(data) {
toastr.success('changes saved successfully', 'Success');
}
and my api controller (mvc) is like
public IHttpActionResult Post(CPatient Patient,EmailDetails emailDetails=null)
{
}
and in factory
return{
api{
'REGISTER_PATIENT': '/api/patients/add
}
}
post: function (api, data, headers) {
var deferred = $q.defer();
console.log(api);
$http.post(api, data,headers)
.success(function (data) {
deferred.resolve(data);
})
.error(function (err) {
deferred.reject(err);
});
return deferred.promise;
},
but when i am invoking the api, it returns a 500 internal server error and I do not know where the problem is?
Where am I going wrong?
Your api url is wrong; there isnt any action 'Add' in your controller (unless you have attribute routing with action name as 'add' ); POST 'api/patients' should work if "Patients" is your controller name.
Rename 'clinicalRegistryPatient' to the exact param name in the Post method; in this case, it is 'Patient'

AngularJS Save File From ASP.NET MVC Controller

I am returning a file from an ASP.NET MVC controller and I want to download it as an attachment using AngularJS.
MVC Controller:
return File(renderedBytes, mimeType);
AngularJS:
function generatePDF(reportRequest) {
var reportController = "Report";
var controllerUrl = ngAppSettings.homeBaseUri + reportController + "/GeneratePDF";
var deferred = $q.defer();
$http({
method: "POST",
url: controllerUrl,
data: reportRequest
}).success(function (data, status, headers, cfg) {
//window.open(controllerUrl, "_self", "");
deferred.resolve(data);
}).error(function (err, status) {
deferred.reject(err);
});
return deferred.promise;
};
I've tried various ways as suggested on the similar questions about this but I'm not getting it.
I've tried this too.
My breakpoints hit without any problems inside the GeneratePDF controller but nothing happens after that. How would I go about this?
EDIT:
I also tried angular file saver but I'm getting an error that the format should be in BLOB. If I can only convert the response to a blob then I think this might be it.
TIA
If your C# Controller endpoint returns a FileContentResult (which it appears that it does), then you shouldn't need to worry about promises. You can simply do the following...
function generatePDF(reportRequest) {
var reportController = "Report";
var controllerUrl = ngAppSettings.homeBaseUri + reportController + "/GeneratePDF";
window.open(controllerUrl, "_blank");
};
I am doing this in one of my apps and it is working as expected. Is there a particular reason you were using the $q service to return a promise?

MVC Routing (like WebAPI)

I know this sounds like a daft question but is there a way to 'mimic' WebAPI routing style (i.e maybe using the [HttpPost] decoration etc) for a MVC Controller. The gist of my problem is I have a 'container' MVC site. This contain in PreLoad loads up other MVC sites within the areas folder and incorporates them into itself. So it basically acts as a Plugin system. This all works great however I need to add in an API for this site which I thought would be a lot easier just if I made the API as another plugin.
I am using Ninject in my site which again works great getting the dependancies from the plugins all perfectly. The issue is that Ninject automatically detects the MVC Controllers but not the WebAPI ones and I've found out you can't have one project doing both WebAPI and MVC with Nijnect. So my next option is to try and mimic WebAPI within MVC (after all, they are based upon the same thing really.)
I initially thought this would be really easy, default the action name to 'Index' in the routing and them just put the 'AcceptVerbs' decoration on each method. Of course it didn't work.
Does anyone know how I would go about or an alternative to creating something like a RestAPI using only the MVC side (not switching to WebAPI)?
In your RouteConfig.cs file, you can specify which HTTP verb goes to which action by passing an HttpMethodContraint:
routes.MapRoute(
"route that matches only GETs for your url",
"your url",
new { controller = "some controller", action = "some action" },
new { httpMethod = new HttpMethodConstraint("GET") });
This will allow you to define routes to your controller that will mimic WebAPI.
You can use Controllers like usual and have them return the JsonResult. I use this approach for some of my views that need dynamic lists through lookup but don't need to be going to the web api. Along with attribute routing I was able to get web api-like functionality from my MVC
Example scenario is I have a form that fills some fields based on a value selected form a combo box. When a user selects an option I use JQuery to make a call to the WebAPI-like action in my controller.
[RoutePrefix("Pickup")]
[Route("{action=Create}")]
public class PickupController : FrontOfficeAuthorizedController {
[HttpPost]
public JsonResult GetSenderAddress(Guid? addressId) {
if(addreddId != null) {
//Do something to get an address
if(address != null) {
//Only send required info over the wire
return Json(new {
success = true,
address = new {
Address1 = address.Address1,
Address2 = address.Address2,
AddressType = address.AddressType,
CompanyOrName = address.CompanyOrName,
Contact = address.Contact,
Country = address.Country,
PostalCode = address.PostalCode,
Telephone = address.Telephone,
TownCity = address.TownCity,
}
});
}
}
return Json(new { success = false });
}
}
Here is a snippet of the javascript on the client side. Note I'm using Knockout along with JQuery
//Shipfrom properties
self.ShipFromaddressid = ko.observable();
//Update shipfrom address based on id
self.ShipFromaddressid.subscribe(function () { getAddress(); });
var getAddress = function () {
var selectedAddressId = { addressId: self.ShipFromaddressid() };
$.ajax({
url: '#(Url.Action<PickupController>(c=>c.GetSenderAddress(null)))',
type: 'Post',
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify(selectedAddressId),
success: handleResponse
});
};
var handleResponse = function (data) {
if (data.success) {
//console.log(data.address);
self.ShipFromCompanyOrName((data.address.CompanyOrName) ? data.address.CompanyOrName : "");
self.ShipFromContact((data.address.Contact) ? data.address.Contact : "");
self.ShipFromTelephone((data.address.Telephone) ? data.address.Telephone : "");
self.ShipFromAddress1((data.address.Address1) ? data.address.Address1 : "");
self.ShipFromAddress2((data.address.Address2) ? data.address.Address2 : "");
self.shipfromtowncity((data.address.TownCity) ? data.address.TownCity : "");
self.ShipFromPostalCode((data.address.PostalCode) ? data.address.PostalCode : "");
self.ShipFromCountry((data.address.Country) ? data.address.Country : "");
self.ShipFromAddressType((data.address.AddressType) ? data.address.AddressType : "");
}
};

Talking to a Web API from a Webforms application

I have an asp.net webforms application as my UI layer. This application is responsible for sending an object list down to my DAL Class Library which will then send this object list to a WebAPI for processing.
The WebAPI needs to retrieve the object list, do the processing and send an OK status code back.
Is this possible? If is there any good documentation on how this is done?
Here is what I have in my webforms app:
public static async Task<bool> MyFunction(IList<string> Ids)
{
using (var client = new HttpClient())
{
bool success = false;
client.BaseAddress = new Uri("http://localhost:9000/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// HTTP GET
HttpResponseMessage response = await client.GetAsync("api/products/MyProcessFunctionName");
if (response.IsSuccessStatusCode)
{
success = true;
}
return success;
}
}
I need to figure out how to send the list of string Ids to the WebApi processing function as a parameter.
I assume that you already know how to setup Web API controller in your project.
Here is a code sample for sending data from UI back to Web API controller method, which will then save that data in database,
Step 1:
In your front-end, I hope you will have a custom javascript file which handles any button click event. On that, try to send the data from UI to Web API using a POST method as shown below,
var StaffSaveRequest = {};
StaffSaveRequest.StaffDetails = {};
StaffSaveRequest.StaffDetails.Name = "Test Name";
$.ajax({
url: 'api/Staff/SaveStaff', //this is the path to web api controller method
type: 'POST',
dataType: 'json',
data: StaffSaveRequest,
success: function (response, textStatus, xhr) {
//handle success
},
error: function (xhr, textStatus, errorThrown) {
if (textStatus != 'abort') {
//handle error
}
}
});
Step 2:
Add a controller class as shown below and see the inline comments. This controller class will then interact with method in Data Access layer for saving any information.
public class StaffController : ApiController //inherits ApiController
{
[HttpPost] //add post attribute
public HttpResponseMessage SaveStaff(StaffSaveRequest staffSaveRequest)
{
try
{
var result = StaffManager.Save(staffSaveRequest);//save in database using a method in data access layer
return Request.CreateResponse(HttpStatusCode.OK, result);//result the response back
}
catch (Exception ex)
{
//log error
}
}
I hope this will give you some idea on where and how to start. Reply back, if you still have issues/questions.
You can use the Microsoft.AspNet.WebApi.Client to use your restful API.
Here is an official example from the asp.net site:
http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client
If you need call your custom function MyProcessFunction first you need to define the function in the controller
public IEnumerable<string> MyProcessFunctionName()
{
return new string[] { "value1", "value2" };
}
after that, if you need to call it by name client.GetAsync("api/products/MyProcessFunctionName") you need to change the RouteConfig file to allow API calls by action name:
Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { action = "get", id = RouteParameter.Optional }
);
It's possible to call WebApi from your webforms project. Here is a sample using WPF to call WebApi, but call should be same for webforms:
http://www.codeproject.com/Articles/611176/Calling-ASP-Net-WebAPI-using-HttpClient

Categories

Resources