I don't have much experience working with resource files, but the little that I have is from Web Forms. There from what I can tell is you create a resource file called let's say InternalMessages.resx and then you create a Spanish version Errors.es.resx. Now if I have set up my code correctly for choosing language, all I have to do it call InternalMessages.MyMessage and it will choose the right language, regardless of what page you are on.
In core, this concept doesn't seem to work. no matter which language I switch to, it just uses the English translations. From reading the documentation, it appears that core wants me to create resource files on the page level, however, I find this very bad practice because it doesn't follow the DRY principle. Sometimes we have values that are used on more than one page and if we decide to change verbiage of that value, we have to go and find it everywhere in the system, other times you may miss that you already have a translation for that or something very similar that would do and you end up paying for translation all over again.
I want to segregate my resources into categories and use them like that. So having the InternalMessages.resx file is how I want to go, however, that doesn't seem to work for me. Here is a SO answer I followed to setup my localization. Localization in Asp.Net Core
So I have a working drop-down with languages, but the code just always pulls the values from InternalMessages.resx versus InternalMessages.es.resx when I switch to Spanish. Why is that?
public class HomeController : Controller
{
public IActionResult Index()
{
ViewBag.Test = InternalMessages.Test;
return View();
}
}
In the view I have:
<p>#ViewBag.Test</p>
I have also tried doing this:
public class HomeController : Controller
{
private readonly IStringLocalizer<InternalMessages> _localizer;
public HomeController(IStringLocalizer<InternalMessages> localizer)
{
_localizer = localizer;
}
public IActionResult Index()
{
ViewBag.Test = _localizer["Test"];
return View();
}
}
But in this case the value I always get is Test
I also tried injecting directly in the View but the result is same as above, just a word Test
#inject IHtmlLocalizer<InternalMessages> SharedLocalizer
<p>#SharedLocalizer["Test"]</p>
Related
I'm learning Asp MVC.
I've been doing WPF MVVM programs for two years already, but i also need to learn ASP which is a common language used in web development in my country as far as i know. And i have also knowledge in c# so i think adjusting will not be very hard, but i'm already facing a lot of problems in making my website work. I tried reading about ASP and MVC but i learn by doing things and from my mistake than reading it. So i decided to give it a try.
I created an EMPTY MVC project using Visual Studio Community Edition 2017
I already created the Layout Page and the First Controller and the First View and its totally working fine.
This is the screenshot
Then i create the second controller. Then the problem comes in.
I created a new controller named NewPostController and ADD View for it like this
But it create another folder with the name of the View and inside it is the view it created
I don't want it to organize that way.
So i dragged the NewPost.cshtml into the admin folder. Run the application then i received an error saying
The resource cannot be found.
Requested URL: /Admin/NewPost
I did a search for a solution but i can't solve the problem
I tried specifying the view name
public ActionResult NewPost()
{
return View("~/Admin/NewPost");
}
Most of the solution i read is specify the View Name. But i can't make it work. What are the things that i missed? Or not understand? Thank you.
MVC have sort of a naming convention where if your controller is named FooController then your views should be keep in a folder name Foo.
Inside this controller you will have your
public ActionResult <name of view>
name exactly the same as the view for easy referencing.
So when you have a view under the Foo Folder and the name of that cshtml file is Hello
then inside the FooController, you have a
public ActionResult Hello(//parameter here){
//body here
}
Hope you understand my explanation.
Also to answer your question. I'm assuming you want the NewPost.cshtml as part of the admin folder. Just add
public ActionResult NewPost()
to your admin controller and then you can use
localhost/admin/NewPost()
If i miss anything or any error, please comment hehe answered this in a bit of a rush
Just move your NewPost action to your AdminController as such:
public class AdminController : Controller
{
public ActionResult Dashboard()
{
return View();
}
// Here you go
public ActionResult NewPost()
{
return View();
}
}
This is default MVC structure if you want both Dashboard and NewPost views to be in the Admin folder
This question already has answers here:
How to serve html file from another directory as ActionResult
(6 answers)
Closed 5 years ago.
We have a .NET 4.0, MVC 2 project, where the HomeController looks like this:
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
return View("~/client/index.html");
}
}
All is fine.
But, when we start linking to .NET 4.5 and MVC 4, the runtime can't seem to find this index.html! We get this error:
The view '~/client/index.html' or its master was not found or no view
engine supports the searched locations. The following locations were
searched: ~/client/index.html
How could this be! What might we be missing here.
I've never seen MVC using straight html pages. This is a more typical setup:
Controller
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
return View("Index");
}
}
The view would be /views/Home/Index.cshtml. By default MVC wants views to be in the views folder in a folder corresponding to the controller name.
If you want to have the layout broken into a separate file it would typically be in /views/Shared/.
If your HTML page is self-contained you should be able to move it and rename it to index.cshtml and add the following somewhere on the page.
#{
Layout = null;
}
Take care when locating your html page. Placing it inside a view folder where, by the MVC rules, a controller would be expected to do the handling, causes errors in my testing. Here's one way to make it work, though this isn't really coding to MVC pattern:
You can then reference the page:
Notice I've stepped outside the controller/view structure (not recommended for MVC)
To make it fail, which I'm assuming is similar to what is happening for you:
(notice the html is placed in a view where we'd expect a matching controller method to serve it to a caller)...
But...
So if you insist on going this approach perhaps you can set up a content folder outside your MVC controller/view structure and place your html there. But, again, not to beat the subject to death, you could easily convert this to cshtml and serve it up via a simple method in a controller. Just my two cents' worth..
I have recently started working on MVC application. However my first plan was to create two separate projects in the same solution. One asp.net MVC web application and second is asp.net WebAPI. So that my Web Application will talk to Web API which in return will send JSON response to application which will be converted to View Model for View.
Workflow Diagram :
As i studied more i got to know that API controller and controller both merged into a single controller class in MVC 5. so here is my question how can i achieve the above workflow in MVC 5.
MVC 5 Workflow Diagram
So here comes the problem for me in MVC 5 or i am unable to understand it completely E.g :
UserModel
public class UserModel
{
Public int UserId {get;set;}
Public string Username {get;set;}
}
UserController
[HttpGet()]
public IActionResult GetUser(int id)
{
// do some work
return View(userObject);
}
View
#model UserModel
<h1>#Model.Username</h1>
but when i call the above method from mobile it will give me the rendered html which is not useful for me so do i need to create another method in the same controller in which will return data in JSON.
[HttpGet()]
public IActionResult ApiGetUser(int id)
{
// do some work
return JSONResponse.. ;
}
Modifying method :
[HttpGet()]
public IActionResult GetUser(int id)
{
// calling api get user method
ApiGetUser(int id); // return json
// do some work to convert json into ModelObject
return View(userObject);
}
And if any one mobile app needs data it can call m APIGetUser Method but in this scenario for me its tedious and no of extra methods will be added in the same class. So my basic question is my understanding towards the flow is wrong or am i missing somethings because if below mentioned workflow is right than i would prefer the first one as its separate WebAPI project and easy to maintain ?
In my opinion both diagram are architecturally correct.
But you should consider SRP and separation of concern this: if MVC controller + WebApi controller are both an entry point to your application, running the same code and returning it in 2 different way, they are actually doing 2 different things isn'it? One serve the view and the other one the json.
Plus if you have to render a view there are naturally some behaviuour that isn't common with your web api (cache or rendering partial view for example).
If you think the same, you should leave aside that in MVC 5 both MVC+WebApi controller are under the same class and split it for the reason above.
Hope it helps!
So I want to have a status page that will show a different layout of the equipment depending on who's using it which will be a variable defined in the web.config. Should I be creating a separate controller per view? Some of the background functions should be similar but some will probably be different in the future. Or should I have the same cshtml file and hide html markup depending on who's using it or not?
I was thinking of doing something like:
#if(System.Configuration.ConfigurationManager.AppSettings["IsSuperUser"] == "true")
{
Status
}
else {
Status
}
Or is this a bad idea?
There are several options, it all depends on your needs and preferences.
Your code will work, however you must also double check permission in your controller! For example, your url will be "/SuperUser/Status" and "/User/Status". Now, what's stopping non-super user to type in "/SuperUser/Status" to the address bar?
One important rule, never trust the end users! Assume that they will not do what you intend them to do.
Given all, my preference would be to include a variable in your Model to identify the user level (super vs non super), then use that to determine the layout in your views. Remember, you can also change the layout of the view based on variable/expression.
#Layout = Model.IsSuperUser ? "_SuperLayout.cshtml" : "_RegularLayout.cshtml";
Sounds like a view concern. I would pass the config data through a dependency in the controller and render partials:
#if (Model.IsSuperUser)
{
#Html.Partial("_SuperUser")
}
else
{
#Html.Partial("_User")
}
The controller can then do something like:
public ActionResult Index()
{
var vm = new MyViewModel();
vm.IsSuperUser = _config.GetSuperUser();
return View(vm);
}
I currently have a MVC 3 Web Application with around 50 Views.
Is it somehow possible to provide some kind of API next to my Views so everything still works fine and dandy?
My kinda perfect world idea:
Server is running and every request gets to its view. The user can decide in his get request if he wants the raw data in lets say JSON. Additional to the raw data also the Structure/Names of the Viewmodel will be parsed so the Modelbinder can do his stuff.
or another approach might be to somehow deactivate my Views to have only the API available (again with raw data and structure).
Is this even possible (the modelbinder is kinda a big concern) and maybe even without much effort/trouble to do?
If you don't want to do everything all over again with WebAPI, you can implement some ActionFilterAttribute to change the ActionResult based on some querystring f.i.
Something like this:
public class ResultSwitcherAttribute: ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.HttpContext.Request["data"] != null && filterContext.HttpContext.Request["data"] == "json")
{
filterContext.Result = new JsonResult
{
Data = (filterContext.Result as ViewResult).Model,
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
}
}
Then, you'll register that either in application_start or per controller/action like this:
[ResultSwitcherAttribute]
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new TestModel()
{
Web = "http://www.mywebpage.com", Name = "Yngve"
});
}
}
When you now access your url with ?data=json you'll get a JSON-representation of the Model, instead of the view.
EDIT: Code sample updated
Consider adding an ASP.NET Web API to your app. It's extremely simple to implement, entailing little more than adding an API controller with methods corresponding to your REST actions. I don't know how one would go about adding this to an MVC 3 app, but I have a recipe for MVC 4 Internet Applications in this stackoverflow question. So, if you're fine with upgrading your project so that it is Web API capable, perhaps to MVC 4, I think it'd represent a good alternative.
To learn ASP.NET Web API, this tutorial is a good place to start.