I am building an MVC Web Application with a cshtml + Angular front-end. An important aspect of the application is for the View to update the angular data-table automatically when new Data is retrieved from the custom Data Service.
The Data Service is accessed via an API call in a C# Class on the backend which gets fresh data as a ViewModel List<> on a set interval (roughly 5 minutes) which it then caches. The ViewModel List<> is then passed to the view as an ActionResult parameter return View(List<model>), serialized in our Angular controller and displayed in a table using ng-repeat.
I am relatively new to MVC and right now the only way I know how to get Data from a controller into a View is by passing it directly as an ActionResult parameter. As a result the only way for me to get data into the view requires me to reload the entire page via an explicit action (HTTPPOST, Forced Refresh, FormSubmit etc).
I want to try and use Angular and maybe AJAX(?) or a similar library, to "ask" the Controller that makes the API call and caches the data if there is new data every 10 seconds or so. Then, if there is new data (which there will be once ever ~5min) it will load that data into the View in the background WITHOUT reloading the page, so that Angular can Serialize it and then reload just the table.
This is just to enable users to get the most current data without having the make an explicit action or refresh the page.
I know how to do every part of this except getting the Angular to ask the C# class that makes the API Call if it has made a new Service Call (and stored it in the ViewModel) and then "pulling" the fresh data from that ViewModel into the view without having to return an ActionResult
Edit:
Since this is where most of our problems/confusion have come up, our data service isn't located outside of our application and as far as I know cannot be accessed via a reference to an internal URL. It is a "Connected Service Package" that we have to invoke via a C# function ie
using ServicePackage;
MyDataService = new DataService();
ViewModel.DataList = MyDataService.getData();
This all happens in a Controller Class. I know it's hackey and not how modern web app architecture is done, but it's the best the client could give us to work with. Believe me if we had a data-server or Web-API we could query we would be using $http or Ajax or any of the dozen other ways a View can pull data from an external source.
Related
I started to develp a new project with CQRS/ES. As I understand, one command raised a new event. So, I developped a web api with one action mapped to one command.
List of api action :
[Route("api/user/create"), HttpPost]
public Task<IActionResult> Handle(Commands.Create command)
=> HandleCommand(command);
[Route("api/user/update/name"), HttpPost]
public Task<IActionResult> Handle(Commands.UpdateName command)
=> HandleCommand(command);
In my IHM project developped with Blazor, how to communicate with the web api ?
Foreach change in a textbox, i send a http post ?
it's not really a best solution.
I prefer to add a submit button and send one http post. For this solution, how do I communicate all of user's action to web api ?
I would strongly suggest you to take a look at concepts like DDD. The first thing you have to do is get a clear understanding of your Domain.
Let's say that you're working on a Product Inventory system. In your Blazor app you might well have a "create product" page, containing a form with all the relevant fields (eg. "title", "description", "price" and so on).
The backend would expose a POST endpoint /products accepting a CreateProductDTO (check what a DTO is if you're unsure). The DTO would then be mapped into an immutable command, which will then get sent to the relative handler.
The idea is not to send every single user interaction to the server. You have to make a map of the possible actions exposed by your Domain and work your way up.
Thanks for your time , I have a simple question, in an asp.net MVC application, inside controllers is it possible that along with some methods returning View (ActionMethods) other could act as (or return) Json as a Web API (could be called from external apps).
Just trying to do a proper separations, hence trying to understand.
Thanks much.
You can make an action function like an API. Try something like the this.
// Controller/Action
[HttpGet]
public ActionResult IAmSpecial()
{
if (Request.IsAjaxRequest())
{
string[] objects = new string[] { "Foo", "Bar" };
return Json(objects);
}
return View();
}
This will return the IAmSpecial view if you browse to {domain}/{Controller}/IAmSpecial while it will return a JSON result if you use an AJAX Http Get request on the same url.
while it is possible to have controller methods which return Json data only, there are a number of considerations when you want to expose that data outside of the UI app.
Since you have an MVC app, I expect you have users and a way to login. Your controllers would more than likely be secured in some way, which works for the internal users of the application. Now you want to add one method which effectively becomes an API, available outside of the application and calls to it will have to be authenticated somehow.
What I would suggest is to split this up. You can create a separate project, which is a WebAPI one, in the same solution. The code which prepares the data can live in a class library you can then reference in both your MVC and WebAPI projects.
Your MVC app can call it and then return a view with that data, the WebAPI calls it and simply returns the data. You can now decide on a way of securing your API, maybe using Identity Server or some other way and you can keep adding things to it, without affecting the UI layer.
Your second option is to make the MVC app use the API when it needs to retrieve data, so both your public clients and UI use the same thing.
Whichever option you use, the idea is to not duplicate anything and at the same time provide the security layers you need.
I have a simple asp.net web application project. Which has an order.aspx page showing different items. I have managed to show those items by outputting in
page_load event.
Now I am using JQuery to load item details from the database and show when the user clicks on the items.
This is the JQuery I am using
$(".item").click(function(){
$.post("Lookup.asp",
{
Id: $(this).id
},
function(data, status){
alert("Data: " + data + "\nStatus: " + status);
});
});
Now I want to know how and what is the best way to setup the backend part to provide the data. Currently I am thinking that Lookup.aspx page on its page load event will receive the id from request object, I query the db populate the data and send it back through the response object. I am not sure if this is the right way of doing it.
I have not set this yet, because I was thinking if we create a separate page to do this then I will have to create more pages for other type of queries (I will have different queries like checking for status of an item in db).
Another problem I was thinking with this approach will be that there will be pages which are just serving the data and we dont want to show them to the public. If someone will have the name of the pages they can access them which we dont want.
And I am using Entity Framework it that matters in anyway.
For the Web Service part. The best and easiest way to go is WEB API. Just write a controller method and it becomes a web service which returns json or xml.
Using Web API with ASP.NET Web Forms
Now about the second part is tricky.
IF your users are not logged in then , the method has to be public in order for someone to have access . So either through ajax either from just having the url someone will and must be able to access the method.
A way to tackle this , is to encrypt-decrypt your product ID's .
Or use authentication on web api.
https://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api
I want to run a version consistency check between the website and database on every page in the software I work on to see whether one or the other is out of sync. (background: someone could upgrade while a user is using the software, so restricting the check to the sign in page isn't realistic - also why the check is required on any page in the software).
I am not in control of the deployment, as the customer hosts the software themselves on their own hardware.
The front-end is a mixture of asp.net pages and MVC4 (gradually replacing the aspx pages with MVC) , so I can't simply just run the check on Page_Load() in our inner and outer basepages and then have something different for our MVC pages - I would rather not duplicate code for each page type.
Having a look around, I have seen filters which exist for MVC which could be an option for those pages.
I've been investigating HttpHandlers and in theory could restrict the requests down to page load and not static content.
Is there an alternative/better way to do this server side check which would have the code in just one place and would affect both aspx pages and MVC?
Depending on what it should do when its passes the check or fails the check you could set up a new controller Version with an action Check
public class Version : Controller
{
public JsonResult Check() {
return new Json((GetWebsiteVersionNumber() == GetDatabaseVersionNumber()));
}
}
You can then call this endpoint from MVC using #Html.Action in _Layout or in another view and respond accordingly. On the Web Forms side you can then call this end point using the serverside WebRequest class and take appropriate action depending upon the response from your MasterPage PageLoad event or anywhere else you prefer.
Further you could call the endpoint from a common javascript file i(ncluded on both the WebForms and MVC client side includes) and using an AJAX request get the response and deal with it there also.
Excuse syntax errors as I was writing this off the top of my head.
I am working in an environment with many teams who are responsible for specific content on pages. Each team is sharing specific information (common class libraries, and master pages) that each are going deliver different types of content.
Is it possible for an MVC application to do something similar to RenderPartial and pass a model to another MVC application Controller/Action to return content?
So the code for this might look like:
(http://www.mydomain.com/Home/Index)
<% Html.RenderAction("ads.mydomain.com", "Home", "Index", AdModel) %>
Maybe this is not a good idea as another thread has to spin up to server a partial view?
No, RenderPartial/RenerAction can only load views that it can access via reflection, not via HTTP requests to external resources.
If the MVC app for 'ads.mydomain.com' is available to you at compile them then you can utilise its resources via Areas, however it won't pickup the changes if they release a new version to the 'ads.mydomain.com' website without you getting their latest assembly and re-compiling and deploying your app as well.
You can do similar stuff with AJAX where you can load a fragment from another site, however it wouldn't be done server side, and would require the client to have javascript enabled. Also the model would need to be converted to JSON and posted to the request, so its a bit of a hacky solution.
You could write an extension method (lets call it Html.RenderRemote) which does all the work for you of creating an http connection to the target and requests the URL. You'd have to serialize the model and send it as part of the request.
public static string RenderRemote(this HtmlHelper, string url, object model)
{
// send request to 'url' with serialized model as data
// get response stream and convert to string
// return it
}
You could use it as :
<%= Html.RenderRemote('http://ads.mydomain.com', Model');
You wouldn't be able to take advantage of the routes on the remote domain, so you'd have to construct the literal URL yourself, which means if they change your routing rules your URL won't work anymore.
In principal yes, though your question is a little vague.
Have a look at "portable areas" within MvcContrib on codeplex. This technique allows separate teams to develop separate MVC apps that would then be orchestrated by a central application.