Displaying error messages from Controller in View - asp.net-core

I have seen a lot of people say that using Viewdata or ViewBag is not a good practice for this matter(displaying messages from the controller) because of security reasons. Everyone seems to suggest ModelState
My question is what is wrong with using viewdata to display error messages? If we arent supposed to use ViewData then what should we use it for?

As #shenku answered before, ViewData and ModelState reference the exact same thing, if you look at the code for System.Web.Mvc.Controller class you will see the implementation for ModelState is:
public ModelStateDictionary ModelState
{
get
{
return this.ViewData.ModelState;
}
}
and #JimmiTh said,
although the main use of ModelState from an "end developer"'s perspective is in the controller, ViewData is used as a container for all data that's communicated between the controller and the view. Which is why it also needs to include ModelState - because, although you'd rarely use it directly in the view, ModelState is where e.g. many of the HtmlHelper methods actually get the values from by default when rendering the view from a POST action - rather than Model.

Related

Umbraco with MVC Controller

I am working on MVC and i started learning Umbraco, I didn't get how to bind the umbraco page with mvc controller get method to show the database values. can anyone suggest any url or video?
Thansk...
What you're looking for is Umbraco route hijacking.
You can read about it here.
https://our.umbraco.org/documentation/reference/routing/custom-controllers
It's easiest to demonstrate with an example : let's say you have a Document Type called 'Home'. You can create a custom locally declared controller in your MVC web project called 'HomeController' and ensure that it inherits from Umbraco.Web.Mvc.RenderMvcController and now all pages that are of document type 'Home' will be routed through your custom controller! Pretty easy right :-) OK so let's see how we can extend this concept. In order for you to run some code in your controller you'll need to override the Index Action.
So, basically, you "simply" need to create a controller named after your document type, so for example, a document type with the name "TextPage" would need a controller called "TextPageController". Now, if you read through the documentation, you'll find that your "TextPageController" will need to inherit from the RenderMvcController. Here's an example how to achieve this.
public class TextPageController : RenderMvcController
{
public ActionResult Index()
{
return View("~/Views/TextPage.cshtml");
}
}
This forum link may help you:
https://our.umbraco.org/forum/developers/razor/38242-Umbraco-MVC4111-Surface-controller-using-an-AJAX-form

Accessing controls in Razor view from controller MVC4

I am new to MVC. In my application the view page created using razor by designing it from another html page designer. I have doubt that how to access the html controls from the corresponding controller. For example, i create a controller named Home and and corresponding view. Added a text box into it.
<input id="name" type="text" name="txtName"/>
Now i want to get and set the value in text box from controller without using script.
Just like
txtName.text="...."
Is that possible..?
It sounds like you are thinking of things from a Web Forms perspective, e.g. controls, setting properties server-side.
MVC allows much better separation of concerns, that is, each piece should play its part without being tightly coupled to other parts. Having a controller set a property of a textbox in a view means that there must always be a textbox in that view and would tightly couple the controller to that particular view. It is not directly possible and it would be a bad idea even if it was.
That's where view models come in:
// M - model
public sealed class MyViewModel
{
public string Name { get; set; }
}
// V - view
#model MyViewModel
// (usually code to begin a form goes here)
#Html.TextBoxFor( o => o.Name )
// C - controller
public ActionResult MyActionMethod()
{
var model = new MyViewModel { Name = "Hello" };
return View( model );
}
It may seem like an extra step (it is) but it is cleaner, far more flexible, and far more test-friendly.
It would only be possible with another request to the server (e.g. POST, GET) because the Controller code can only run server-side. After processing another request, you could use a ViewModel to populate your HTML text-box while rendering it, but I doubt that is what you are looking for.
If you are familiar with desktop programming (e.g. Window's Forms) and you are looking to immediately change and process fields on an HTML page, you will need to use JavaScript. If you are unfamiliar with web-programming, or even just new to the MVC paradigm, I suggest you try out a few MSDN tutorials.

Can Umbraco pass a model to view

I am quite new to this Umbraco MVC.
I need to pass some data bound to a model to my partial view from the GET action method.
This simply is not working in a regular MVC way.
[httpget]
public ActionResult Membership()
{
SupplierMembershipInfoModel mm = new SupplierMembershipInfoModel();
mm.ProductPackage = "sssssssss";
ViewBag.status = Request.QueryString["status"];
return PartialView("MembershipPartial", mm);
}
my view:
#model Umbraco.Web.Models.SupplierMembershipInfoModel
some html.....
<td>#Model.ProductPackage</td>
I don't get data here...and the debug never hits the action. But it hits any POST action method.
I know i am doing something wrong...but just don't know what the mistake is??
Any ideas??
As #Sebastiaan points out, the best place to start is the Umbraco community site. There is documentation specific to your issue here: http://our.umbraco.org/documentation/Reference/Templating/Mvc/child-actions
In a nutshell, you want to display a child action on your page and Umbraco uses SurfaceControllers for this. A SurfaceController is simply a Controller that inherits from Umbraco.Web.Mvc.SurfaceController. This provides you Controller with access to the Umbraco context - see here (http://our.umbraco.org/documentation/Reference/Templating/Mvc/surface-controllers).
Either way, you should read the whole documentation section on templating as it will give you a lot of insight into how Umbraco MVC is managed.

Html.RenderAction uses Post instead of Get

I have a simple form on my page. When submitted, it checks if ModelState.IsValid and returns the View with the same model if it's not valid.
On the same page, I'm rendering an action that contains another form like so:
Html.RenderAction("AccountNote", new { id = Model.ID });
Everything works fine until I submit the form on my page and the validation fails. When it shows the page again, the AccountNote action's Post event fires when I'd expect the Get event to fire. I guess it makes sense why it's happening since it's the post that action that's rendering the view, but I want the Get event to fire instead.
public ActionResult AccountNote(int id)
{
//code goes here...
return PartialView(model);
}
[HttpPost]
public ActionResult AccountNote(AccountNoteViewModel model)
{
//code goes here...
return PartialView(model);
}
Am I doing something incorrect? Or is there some trickery I have to do to make this work? I would expect the Html.RenderAction to always assume GET instead of POST.
One solution would be to have only one AccountNote() action method. Then it will be called regardless of GET or POST. You might have to modify your logic a bit if you were using POST version of AccountNote().
And you can decorate it with [ChildActionOnly] attribute.
Since I know, there is not any solution for this problem out of the box. RenderAction and Action methods, consider the current request for deciding on to use which verb.
But you can rename them. For example rename the one that is restricted to HttpPost to AddAccountNote and leave the other one with the current name and without specifying its verb.
Would RenderPartial be an option for you?
More discussion on this topic can be found here: RenderAction calls wrong action method

ASP.NET MVC ViewModel inheritance issue

I have the following ViewModels :
public class MyViewModel
{
public BaseViewModel mySubViewModel;
}
public class ChildViewModel: BaseViewModel
{}
I then create a MyViewModel model, which contains a property of type ChildViewModel. In the View, it is displayed just fine.
Then I hit the save button to submit changes to my Model and I call the following controller:
[HttpPost]
public ActionResult Edit(MyViewModel model)
{
return null;
}
To my surprise, the property mySubViewModel is now of type BaseViewModel instead of ChildViewModel ! I have no idea what's going on here. What am I doing wrong ?
To my surprise, the property mySubViewModel is now of type
BaseViewModel instead of ChildViewModel ! I have no idea what's going
on here. What am I doing wrong ?
You shouldn't be surprised by that. You are doing nothing wrong. This is by design. The default model binder sees that your controller action is taking a MyViewModel argument and is attempting to bind the contents of the POST request to it. The default model binder has absolutely no way of knowing that you might have written some derived classes (such as ChildViewModel in your case) and that you want those derived classes to be used instantiated here. The fact that you have passed this concrete view model instance from your GET action to the view has no influence to the POST action. Think of it in terms of HTTP and what the default model binder sees. Think for example that this POST action could be invoked from some completely different client and not from a form submission. Could be for example an iPhone application performing an HTTP request to the POST action. See, now it makes perfect sense. The default model binder can only see the payload of the POST request and the type you specified as action argument. And that's what he does => it instantiates this types and binds its properties from the POST payload data.
So one possibility is to write a custom model binder that will instantiate the concrete instance of your view model you wish. I have exemplified such a custom model binder at this post. In this example I have included a hidden field inside the form that will contain the concrete type of the view model that we would like to be instantiated and then the custom model binder simply uses this information to create this type at runtime.