So, apparently, I'm trying to return an HTML file with help of the Spring Controller.
I already have added Thymeleaf dependencies and also tried the following ways to configure it:
1.
#RequestMapping ("/")
#ResponseBody
public String homeDisplay() {
return "homepage";
}
#Controller
public class HomeController {
#RequestMapping ("/")
public ModelAndView index () {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("homepage");
return modelAndView;
}
}
Anyway, didn't help, I get Whitelabel Error Page.
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Sun Dec 13 20:14:04 EET 2020
There was an unexpected error (type=Not Found, status=404).
No message available
How can I fix it and display the HTML I need.
Try replacing the #RequestMapping with #GetMapping("/") or #RequestMapping(value = "/", method = RequestMethod.GET)
Why? because #RequestMapping will map to any request to that URL, so you have to specify that it's a GET request (I suppose that is what you want to use).
Since you didn't share your frontend code that is sending the request we can't tell if there is a problem there. Please share it as well.
I was running in to a similar problem when trying to get a homepage to show up for a REST API that I was making. The project does not have Thymeleaf though. I used the following and this worked for me. The following code makes the home.html file, stored in resources/static to show up when the application starts. It's a static page and no data is sent to it.
#Controller
public class HomeController {
#RequestMapping("/")
public String welcome() throws Exception {
return "home.html"; //note that this says .html
}
}
For a project that I was using Thymeleaf in, I have the following code which shows the login page stored in resources/templates folder.
#Controller
public class LoginController {
#GetMapping("/login")
public String showLoginForm() {
return "login"; //note that this is just the name of the file with no extension
}
}
Be sure to put the html file in the correct folder. My guess is that since you're using Thymeleaf, you will probably be using some templates.
Related
to give a brief about my situation:
Earlier I was using chart.js for creating charts in my dashboard. Then I came across Quicksight a couple of days back. So I thought of switching to it as it provides better handling without any hassle.
Before Quicksight I was using jsp for my page, js(jquery) for my frontend and Java as my backend (spring-boot) with MongoDB as my database.
Keeping my structure same I just defined a jsp so that the user can be directed to the particular page after hitting on the chats.
Then, in my js file, I have written a (my own defined) ajaxRequest that will direct it to the Java controller:
$(document).ready(
function(){
ajaxRequest("/myService/char/getQuickSight", "GET", "", function(response){
})
}
);
Now I am not able to understand how to go on with my controller class. I have written something like this:
private static AmazonQuickSight getClient() {
final AWSCredentialsProvider credsProvider = new AWSCredentialsProvider() {
#Override
public AWSCredentials getCredentials() {
// provide actual IAM access key and secret key here
return new BasicAWSCredentials("access-key", "secret-key");
}
#Override
public void refresh() {
}
};
return AmazonQuickSightClientBuilder.standard().withRegion(Regions.SA_EAST_1.getName())
.withCredentials(credsProvider).build();
}
For he above code I refered to this
It is also throughing an error:
ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.NoSuchMethodError: com.amazonaws.client.AwsSyncClientParams.getAdvancedConfig()Lcom/amazonaws/client/builder/AdvancedConfig;] with root cause
java.lang.NoSuchMethodError: com.amazonaws.client.AwsSyncClientParams.getAdvancedConfig()Lcom/amazonaws/client/builder/AdvancedConfig;
(I can also provide the full stacktrace..)
But I am not able to understand how to move forward and what to do with the code. So if anyone can help me out I'll really appreciate it.
P.S. I have also added the following dependency in my POM
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-quicksight</artifactId>
<version>1.11.457</version>
</dependency>
I know PRG pattern can prevent duplicate submission(POST) for a page. But I have a JSP page with window.history.back() link. this link take back the user to the previous page that was POST, but all browsers show resubmission warning and suggest to press reload button. I want to allow user go back to that page wihout any confirmation. The POST controller does a search. Inthe JSP page I am using:
...
and the end point is:
#RequestMapping(value="search.htm", method = RequestMethod.POST)
public String searchResults(Model model, #ModelAtrribute(value="search") Serach search, HttpServletRequest request){
......
}
**** I don't want to prevent re-submission.
I can't try it now, so take following example like a "guideline"... anyway I think you should use SessionAttributes within the ModelAttribute in order to keep your model still using window.history.back() link.
So, you could modify your Controller like:
#Controller
#SessionAttributes("searchObj")
public class YourController {
#RequestMapping(value="search.htm")
public ModelAndView searchResults(#ModelAtrribute(value="search") Serach search){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("search-result-page");
modelAndView.addObject("search", search);
modelAndView.addObject("searchObj", search);
return modelAndView;
}
}
Okay, curerntly I am displaying some data on a html page. I have used jquery ajax call which get the data from the specific url on spring MVC application and return data and then use javascript to display data in the table.
#RequestMapping(value = "/students", method = RequestMethod.GET)
#ResponseBody
#JsonView(Views.PublicView.class)
public ArrayList<Student> getAdminsList(HttpSession session) {
//return data
}
Now, my question is, I get data as I required via ajax, but I do get data displayed in the browser if I just go through url: www.example.com/students - will display JSON data.
Is there anyway to avoid display this data not in browser but only in ajax call?
Anyway, I just found the answer for this after lots of googling and I thought sharing it would be good thing. So, basically what is the logic for this restriction is that, whenever a call is made from ajax a special header named X-Requested-With with a value of XMLHttpRequest is attached to the request. the only thing I have to do is check this parameter on my controller.
#RequestMapping(value = "/accounts", method = RequestMethod.GET)
#JsonView(View.Accounts.class)
public List<Account> getAccounts() throws JsonProcessingException {
if(!"XMLHttpRequest".equals(request.getHeader("X-Requested-With"))){
log.info("Request is from browser.");
return null;
}
List<Account> accounts = accountService.findAccounts();
return accounts;
}
you can read the full article on this blog. http://www.gmarwaha.com/blog/2009/06/27/is-it-an-ajax-request-or-a-normal-request/
Maybe feels like being a problem[#JsonView(Views.PublicView.class)]. You check PublicView.class
Read to description. link : enter link description here
#RequestMapping(value = "/accounts", method = RequestMethod.GET)
#JsonView(View.Accounts.class)
public List<Account> getAccounts() throws JsonProcessingException {
List<Account> accounts = accountService.findAccounts();
return accounts;
}
I am new to WebAPI programming .Here is what have I done
Created ASP.NET web Application SampleWebApiProject in Visual Studio 2013
under .NET Framework 4.5.2
Selected MVC and checked Web API under [Add Folders and core references for].
using Nuget package installed knockout.js ,knockout-validation.js etc etc.
In my code for Login.cshtml I have html button
<div>
<button type="button" class="btn btn-info" data-bind="click:$parent.login">
Login
</button>
</div>
And on my click button I have
self.viewModelHelper.apiPost('api/account/login', unmappedModel,
function (result) {
}
And I have created API Controller called AccountApiController
public class AccountApiController : ApiController
{
[HttpPost]
[POST("api/account/login")]
public HttpResponseMessage Login(HttpRequestMessage request, [FromBody]AccountLoginModel accountModel)
{
return null;
}
}
However when I inspect the click event in Chrome developer tools I get an error response
POST http://localhost:64436/api/account/login 404 (Not Found).
this is my WebApiConfig
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Am I working with right type of application ?
Screenshot
Try:
self.viewModelHelper.apiPost('api/accountapi/login', unmappedModel,
function (result) {
}
and API Controller
public class AccountApiController : ApiController
{
[HttpPost]
[POST("api/accountapi/login")]
public HttpResponseMessage Login(HttpRequestMessage request, [FromBody]AccountLoginModel accountModel)
{
return null;
}
}
Your account controller is named accountapi and not account, so webapi can't find any controller called account.
I'm not sure, but your parameters look wrong in your webapi controller...
Why would you add HttpRequestMessage as a parameter?
You have called your controller AccountApiController and so api/account/login should be accountapi/login
Web API has a strict calls when it comes to MVC architecture.
If you call POST. It means that the API will really CREATE a new Entity, and Does NOT, make other request to be returned.
So meaning, the WebAPI is not custom API function Call that you thought it might be.
It is different from creating an individual API to Creating an web API inside an MVC Application.
Here is are some Notes.
GET : Retrieve an entity
PUT : update an entity
POST : create a new entity
DELETE : remove an existing entity.
so let us say you have an API for Account Models. I will say Models cause when creating an Web API. You need a Model. Unless you're creating your custom API. Outside the MVC.
Now you did this. api/account/test
What it will do is use the [GET] function.
Whatever function you have in the account controllers that have a Data Annotation of [GET] will be executed. And return you something.
And No. Don't use Login as the name of the Method just use GET as you can't really tell the Web API which function to use. It WILL use the one with the GET data annotation. So entering
api/account/ login <---- this will not call the login method, it is entering a string data to be passed to the Get Method.
[HttpGet]
public IEnumerable<string> Get()
{
return "No Value";
}
[HttpGet("{id}")]
public IEnumerable<string> Get(int id)
{
return "There is a value";
}
Now if you want the POST to be Called. Simply create a A Form that has a method of POST. Or JQuery Javascript and call generate the POST method for them. You can't write the Method call in the address bar. You just have to use the right kind of request to call the specific function or function with overload.
I would like to generate some JavaScript on the server side in ASP.Net MVC. Is there a view engine that supports this? Ideally I would like to be able to get JavaScript from an url like:
http://myapp/controller/action.js
I've looked at the MonoRail project, and they seem to have this feature, but it's very lacking in documentation, and I can't find any ports to ASP.Net MVC.
Edit: The idea is to be able to render a page both as standard HTML by using a url like:
http://myapp/controller/action
and as js (specifically an ExtJS component) by using the first url in the question. There would be only a single action in the controller, but two views: one for HTML and one for JS.
Edit 2: I basically wanted to achieve the same result as router extension parsing/request handling in CakePHP.
I wanted to extend this idea to not only allow Javascript views, but more or less any type of document. To use it, you just put the views for *.js urls in a subfolder of your controller's view folder:
\Views
+-\MyController
+-\js
| +-Index.aspx <- This view will get rendered if you request /MyController/Index.js
+-Index.aspx
The class is a decorator for any type of ViewEngine, so you can use it with NVelocity/WebForms/Whatever:
public class TypeViewEngine<T> : IViewEngine where T : IViewEngine
{
private readonly T baseEngine;
public T BaseEngine
{
get { return baseEngine; }
}
public TypeViewEngine(T baseEngine)
{
this.baseEngine = baseEngine;
}
public void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
"TypeViewEngine",
"{controller}/{action}.{type}",
new {controller = "Home", action = "Index", type = "html"}
);
}
public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName)
{
var vars = controllerContext.RouteData.Values;
if(vars["type"] != null && vars["type"].ToString() != "html")
{
viewName = string.Format("{0}/{1}", vars["type"], viewName);
}
return baseEngine.FindView(controllerContext, viewName, masterName);
}
public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName)
{
return baseEngine.FindPartialView(controllerContext, partialViewName);
}
public void ReleaseView(ControllerContext controllerContext, IView view)
{
baseEngine.ReleaseView(controllerContext, view);
}
}
Then, in your Global.asax.cs file:
protected void Application_Start()
{
var ve = new TypeViewEngine<WebFormViewEngine>(new WebFormViewEngine());
ve.RegisterRoutes(RouteTable.Routes);
RegisterRoutes(RouteTable.Routes);
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(ve);
}
Thanks for everyone's help with this!
Based on your edit I'll try with a new answer asumming you need json data for ExtJS. I've just tested it in the app I'm building and it works fine. First you need two routes
{controller}/{action}.{format}
{controller}/{action}
Now the Controller class has a Json method to serialize whatever object you want and it's a JsonResult so you can just use:
public ActionResult List(string format) {
// logic here
if (string.IsNullOrEmpty(format)) {
return View();
} else if (format == "js") {
return Json(object_to_serialize);
}
}
The July 2007 ASP.NET Futures release has the new Managed JScript (I can't find a newer one). I've successfully batted it around a bit - but beware, you will probably be forced to do some extra work, the .ASPX parsing for JScript is unusably buggy.
http://www.microsoft.com/downloads/details.aspx?FamilyId=A5189BCB-EF81-4C12-9733-E294D13A58E6&displaylang=en
You don't necessarily need view engine for that, just return plain text result.
Here is a controller (MonoRail) I've used to render some user culture settings in a javascript object:
[ControllerDetails("js")]
public class JavascriptController : Controller
{
private ISessionContext sessionContext;
public JavascriptController(ISessionContext sessionContext)
{
this.sessionContext = sessionContext;
}
public void CultureInfo()
{
var scriptformat = #"var cultureInfo = {0};";
var json = Context.Services.JSONSerializer.Serialize(getJSONiZableCultureInfo(sessionContext.CurrentCulture));
RenderText(String.Format(scriptformat, json));
}
object getJSONiZableCultureInfo(System.Globalization.CultureInfo culture)
{
return new
{ // add more there
culture.NumberFormat
};
}
}
for more complex things for which raw text rendering would smell, any view engine would work.
Also you are not forced to use .js extension to put the url in your script tag.
I had to do something very similar, and I used the nvelocity view engine from MVCContrib - technically you could use the default aspx view engine, but I found that the nvelocity syntax was a lot more straightforward for puting out script (don't worry if you haven't used it before - I spent about 10 minutes figuring it out!).
Then you just need to add a route to the route table to handle directing your .js url to the action!
EDIT
Can't verify this as I don't have visual studio to hand but for the route, you might have something like this:
RouteTable.Routes.Add(new Route
{
Url = "[controller]/[action].js",
Defaults = new { controller="home", requestType="javascript" }, // Whatever...
RouteHandler = typeof(MvcRouteHandler)
});
RouteTable.Routes.Add(new Route
{
Url = "[controller]/[action]",
Defaults = new { controller="home"}, // Whatever...
RouteHandler = typeof(MvcRouteHandler)
});
Requests ending in .js should go through the first route - extensionless requests fall through to the second.
Then your action could have a requestType param:
public ActionResult MyAction (RequestType requestType)
{
if(requestType == RequestType.JavaScript)
{
... new nvelocity view to render javascript
}
else
{
...
}
}
As for directory structure - you're on your own with that! Not because I don't want to be helpful, but more down to the fact that you have flexibility to do what you want with it!
If you just want to generate a javascript based on the ViewData you can create your own custom result. Here is an example.