MVC Routing (like WebAPI) - c#

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 : "");
}
};

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

C# MVC Calling a method in different path using AJAX

I have a HomeController in my ASP.NET MVC application in folder "Controllers". My View is in: "View/Home/Index.cshtml" (look at my figure below).
I am using Ajax to get some json file every a few second. Problem is in Ajax URL, because I really don't know and didn't find, how to tell that property, that it has to go back a few folders and then find the HomeController.
My Solution looks like this:
Here is a method in my HomeController:
[HttpGet]
public ActionResult GetRandomFeed()
{
Item i = ss.getRandomFeed();
return Json(new { Source = i.Media.Source, Avatar = i.User.Avatar, Text = i.Text, Name = i.User.Name }, JsonRequestBehavior.AllowGet);
}
My AJAX in the View:
setInterval(function () {
$.ajax({
type: "GET",
url: '/HomeController.cs/GetRandomFeed', // Of course I have tried a lots of attempts in here
contentType: "application/json;", // Not sure about this
dataType: "json",
success: function (response) {
console.log("Success :)");
},
error: function() {
console.log("Error!");
}
});
}, 2000);
All I want to get that JSON file (or can be even an array of strings) and use it in my Success function. It is a simple Slide Show and JSON contains the URLs that I want to show in the page every X seconds (just changing source of an image that is in that JSON file).
I couldn't find anything like this. How to use that URL correctly OR found something similiar for WebForms but cannot use it in MVC.
Change your AJAX URL declaration to:
url: '/Home/GetRandomFeed'
Remove the .cs
Or you can also do, assuming this view is under your controller:
url: '#Url.Action("GetRandomFeed")'
In my experience, it doesn't seem enter the function is just because the JSON return from the controller doesn't include Status = "OK"
[HttpGet]
public ActionResult GetRandomFeed()
{
...
...
return Json(new
{
Status = "Ok", ...
}

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?

How to convert url.HttpRouteUrl to a normal string url?

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

Call a class in javascript in visual studio

I have a controller class that I get data from database and return it in a function, Now I want to call this function in a js and set the data in variables to show in a page:
My code looks like: exampleController.cs
namespace iSee.WebApiHse.Controllers
{
public class expController : StandardController
{
public expController(
first myService,
ISystemSettings systemSettings,
IService myExpService)
{
_myService = MyService;
_systemSettings = systemSettings;
_myExpService = myExpService;
}
// GET data
public ActionResult Myexample(int id)
{
var elementIds = _systemSettings.ExpIds;
var myElements = CacheService.AllVisibleElements
.Where(x => elementIds.Contains(x.Id)).ToList();
var container = _kpiContainerService.Find(id);
var result = _myService.MonthByContainer(myElements, container);
return AsJson(result);
}
}
}
This works and I get the data. Now I have myExp.js that I need to use these data in it. How can I do that?
Thanks
You need to execute $ajax(..) (jquery syntax) request to your controller to pass and get compute information from the server.
For this your controller method, that you're going to call, has to be exposed for HTTP access.
More details on :
How to call controller method from javascript
Do you want work with your controller in View by JavaScript? It isn't good idea. You should pass Model to View and work with it or ajax and recieve json-data
An example that uses jQuery-ajax to call your C# method:
// javascript
var id = 987;
$.ajax({
url : '/expController/Myexample/',
type : 'GET',
data { id : id },
dataType : 'json', // <-- tell jQuery to decode the JSON automatically
success : function(response){
console.log(response);
}
});
This would call your method, passing in the value of id, then it would decode the JSON into the response object.
For plain Javascript ajax (no jQuery) see MDN Ajax.
You need to make a request to the Action Myexample. Usually this is done via AJAX:
In your view you could have:
function makeAJaxCall(idToSend) {
$.ajax({
url: '#Url.Action("exp", "Myexample")',
data: { id : idToSend },
type: "POST",
success: function(data) {
$("#HTMLElement").val(data.YourData);
}
});
}
Your response will come back in the data variable if the AJAX call succeeds. I have provided an example to show you how to change the value of an HTML element with the ID HTMLElement.
To invoke the function you can do:
makeAjaxCall(100);
You may load the JSON data in a var and pass it to the function in expjs.js, as:
var data = data_from_ajax();
exp_js_function(data);
data_from_ajax() would receive JSON data from your controller and action method.
Please consider this as a starting point and not as a copy-paste solution

Categories

Resources