How do I access ModelState in a Razor Helper - asp.net-mvc

I have created a razor helper using the
#helper MyHelper(string param) {
}
syntax. I need to be able to access the model state to determine if I should add error classes to the elements. How would I access this? Intellisense does show ModelState but it is always null.
In a razor page I would use ViewData.ModelState but ViewData doesn't exist in the context.

You need to explicitly pass the view context from the view when you call this helper method.
#helper MyHelper(string param,ViewContext context) {
<div>
#foreach (var modelStateVal in context.ViewData.ModelState.Values)
{
foreach (var error in modelStateVal.Errors)
{
<p>#error.ErrorMessage</p>
}
}
</div>
}
and in the view where you want to call this,
#MyHelperClass.MyHelper("Hello",this.ViewContext)
Another option is to create an Html Hepler method

Related

pass a parameter to html partial and retrieve value inside the partial html

How do I pass a parameter to html partial and retrieve value inside the partial html?
#Html.Partial(MVC.Cans.Shared.Views.CanViewModels, Model, UserExists);
The logic wether UserExists is inside the partial AND I do not want to change my viewmodels for this task.
How would you solve that?
You can use the 3rd parameter of #Html.Partial to pass additional view data to the partial
#Html.RenderPartial("yourPartialName", yourModel, new ViewDataDictionary { { "userExists", true} });
The in the partial you can access it using
#ViewData["userExists"];
The cleaner way would be to change the model to include that second value but if you dont want to do it, i'd say you use the Renderpartial method with takes in a View data dictionary type:
Html.RenderPartial(
"partialview",
Model,
new ViewDataDictionary { { "UserExists", UserExists} }
);

ASP MVC 4 - binding and passing data from view to controller in repeating controls

Being new to ASP MVC, I met the following problem.
I have a list of "repeating" controls on my page, which are presented by the following Razor code:
#model BankBLL.Interfaces.ISecureFolder
...(some irrelevant code here)
<header><h3 >Commitee list</h3></header>
#foreach (var commitee in Model.Commitees)
{
<a href="#Url.Action("CommiteePage", "SecureFolder", commitee)">
<div class="commiteeButtonImageContainer">#commitee.Name</div>
<img src="~/Images/CommiteeButtonImage.png"/>
</a>
}
Model.Commitees here is a List of ICommitee objects, that means that I am trying to "bind" each Url.Action to a corresponding ICommitee commitee object.
However, when it comes to my controller action:
public ActionResult CommiteePage(ICommitee commitee)
{
return View("CommiteePage", commitee);
}
looks like I am making it a wrong way, because application returns "Cannot create an instance of an interface." error, that means that application is unable to retreive required commitee object when the action link is clicked.
Is there a way to bind each row "item datacontext" (ICommitee object in this case) to correspoding Url.Action?
Unfortunately could not post it earlier due to reputation regulations.
Finally resolved this issue due to good explanation at:
HTML.ActionLink method
When you try to pass an argument from Url.Action or Html.ActionLink - you have to specify explicitly the final "null" argument responsible for html arguments.
In my case the following code works correctly:
slightly changed controller action (now receives just name instead of commitee object itself)
public ActionResult CommiteePage(string commiteeName)
{
return View("CommiteePage", SecureFolder.Commitees.First(o=>o.Name == commiteeName));
}
and changed syntax for html calling this action:
#foreach (var commitee in Model.Commitees)
{
<a href="#Url.Action("CommiteePage", "SecureFolder", new { commiteeName=commitee.Name }, null)">
<div class="commiteeButtonImageContainer">#commitee.Name</div>
<img src="~/Images/CommiteeButtonImage.png"/>
</a>
}
Now view correctly passes the name of selected commitee to controller so that I can redirect to corresponding commitee view.
Thank you all for helping to resolve this issue!
The main problem is that the default model binder cannot create an instance of an interface. Try to be more specific, i.e. public ActionResult CommiteePage(ImplementedCommiteeType commitee). You can also create a CommiteeViewModel: ICommitee class in which you can transport your structures (in Controllers and Views only).
Or you can create your own model binder which knows what to implement. This is slightly more complicated.

Can one MVC Edit Template delegate to another?

I have a strongly-typed Razor 2 editor template. When the view model meets certain conditions, I want the view to delegate to an alternative template of the same type. I use the TemplateName argument to the EditorFor helper to select the alternative template:
#model MyType
#if (Model.IsSpecialCase)
{
#Html.EditorFor(m => m, "SpecialCaseTemplate")
}
else
{
#* Default markup *#
}
Problem is, Razor does not call the alternative template; it simply passes over the EditorFor method. If I change the type of the second template, it shows it correctly. I can work around this using a Partial View, but I would rather not, as I have a scheme going with Editor Templates that I want to stick to.
Anyone know how I can get this to work?
Edit
Looks like this has something to do with the behaviour described here: ASP.net MVC - Using EditorFor with the same model type twice. In short, that MVC does not support using the EditorFor method on the same object twice.
The best way to do this, is by returning a different view from your Controller:
public ActionResult someaction(){
var Model = ...;
if (Model.IsSpecialCase){
return View("SpecialCaseTemplate");
}
else{
return View();
}
}
Alternatively, you could do in the view like this:
#model MyType
#if (Model.IsSpecialCase)
{
Html.RenderPartial("SpecialCaseTemplate", model);
}
else
{
#* Default markup *#
}

ASP.NET MVC - Is partial view the right place to check if model is null or empty?

I have the following partial view:
#model IEnumerable<Foo>
<div id="foo">
#foreach (var foo in Model)
{
...
}
</div>
If collection is null or empty, I'd like to display some user friendly message, otherwise I'd like to list all collection items. Shell I make that check inside partial view, or inside calling method? What the best practice in this case and why?
Thank you!
Yes, the partial view is the right place - the reason to use a partial view is so your page only needs the view name and a reference to the collection. If you add the IsEmpty logic to the top level page you lose that encapsulation.
I'm not 100% familiar with Razor syntax, but I would create UI helper for that. To keep View simple I use following "rules": if I ever get if statement or a loop then I'll create UI helper.
I have static class for each context. Let's say I have a music store.. then I would have class called AlbumHelper
public static class AlbumHelper : {possible inheritance\
{
public static string CreateAlbumList(Model model)
{
// TODO: create list here using technique you prefer
// <ul><li>empty</li></ul>
return string.Empty;
}
}
That one I would call using (remember to add namespace to your Web.config):
<%= AlbumHelper.CreateAlbumList(Model) %>
If it would be commonly used control then I would create extension, so that it would be created using this line.
<%= Html.AlbumList(Model) %>
Here is a link to short tutorial for creating extension

Correct way to write an ASP.NET MVC action returning a PartialViewResult

I have written an Action method for an ASP.NET MVC controller, which is being used to provide a model to a usercontrol.
public class ProductsController : Controller
{
public PartialViewResult ProductSummary()
{
ViewData.Model = new ProductSummaryModel("42"); // dummy data for now
return new PartialViewResult()
{
ViewData = ViewData
};
}
}
I am using the 'futures' Microsoft.Web.Mvc dll and rendering the control in my main view like this :
<% Html.RenderAction<ProductsController>(x => x.ProductSummary()); %>
What I have here appears to work just fine, but i attempted to google new PartialResult() to see if what I was doing was following the correct patterns.
Currently this search only comes up with 4 results!
So I figured I'm doing somethin wrong here in my controller. Whats the correct way to create an action method that returns a partial view? And what (if anything) is wrong or bad about what I'm doing.
I usually just use:
return PartialView("MyView", myModel);
But this just returns a new PartialViewResult("MyView", myModel) so it is potatoes/potatoes.

Resources