I use umbraco 7 mvc
I simply want to render umbraco field in a partial view. Have no clue how to do it.
#CurrentPage or #Umbraco.Field or RenderMacro etc. do not work
I have the following partial view
#model MvcImport.Models.ImportModel
#{
var formSent = false;
var success = TempData["Success"];
if (success != null)
{
bool.TryParse(success.ToString(), out formSent);
}
}
<script src="#Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#if (formSent)
{
<p>Thanks, we'll get back to you soon!</p>
}
else
{
using (Html.BeginUmbracoForm<MvcImport.Controllers.ImportController>("ImportExcel", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div>
#Html.LabelFor(x => x.FileUpload)
#Html.TextBoxFor(x => x.FileUpload, new { type = "file", name = "Files" })
#Html.ValidationMessageFor(x => x.FileUpload)
</div>
<div>
#Html.LabelFor(model => model.FileType)<br />
#Html.DropDownListFor(model => model.FileType, Model.FileTypes)
#Html.ValidationMessageFor(x => x.FileType)
</div>
<input type="submit" value="Submit" class="btn-submit" />
}
}
I simply want to replace
<p>Thanks, we'll get back to you soon!</p>
with current page field eg.
#currentPage.thankYouCopy
or
#Umbraco.Field("thankYouCopy")
How to do it?
I'm calling the partial in my main view by this:
#Html.Partial("Import", new MvcImport.Models.ImportModel { FileTypes = fileTypes })
Thanks
I haven't tested this at all, but this should get you going down the right path... Best I can tell, you want to replace this:
#model MvcImport.Models.ImportModel
With this:
#inherits Umbraco.Web.Mvc.UmbracoViewPage<MvcImport.Models.ImportModel>
This should give you access to the UmbracoHelper and allow you to access the property like so:
#Umbraco.Field("thankYouCopy")
We are a few things mixing up here. You have a custom model while you are trying to get data from Umbraco Nodes.
You are using a custom model to pass to your view. Like #c0r3yz mentions you could change the model being passed to the view. If you have a RenderMvcController or a SurfaceController this might be a good idea.
If you are happy with your current controller (whatever this is), you can use do #Model.MyPropertyName to display the wanted value. If you do not want any umbraco functionality (like the current node etc), this is perfectly fine.
All field retrieval options you mention are similar to each other. What they do is retrieve information of the current Node. Because you are using a custom model, you can not use them until you inherit your custom model from an umbraco baseclass like discussed before.
#Umbraco.Field("myfield") is a helper method which can assist you with getting and formatting the right field. This is probably the easiest solution for starters. One of the very powerfull features is the recursive = true. See the documentation for more information on this.
#CurrentPage.myField return the value of the field (using dynamics). This is easy to write, but might get you in unexpected situations sometimes.
#Umbraco.Content.GetPropertyValue("myField") returns the value of the field. Does exactly the same as the partial but using (and returning) strongly typed methods/objects. If you use Visual Studio, you probably love the intellisense part.
#Umbraco.Content.GetPropertyValue<ACustomType>("myField") returns the value of the field using ValuePropertyConverters. If you use the previous and don't specify the type, propertyconverters will be used too. But with this notation you can control a littlebit more which type is returned.
I've added some links to the documentation so you can look up more information about the different options.
Related
Situation: I have an ASP.NET Razor page that is constructed of partials.
Some of these are in loops iterating over collections that are members of the main page's view model. These iterated partials use the collections' member types as their own view model.
So the main page Razor looks something like this:
#model MyProject.MainViewModel
#*Other stuff...*#
#foreach (Subtype v in Model.SubViewModel)
{
Html.RenderPartial("MyPartial", v);
}
And the partial looks like this:
#model Subtype
#Html.HiddenFor(t=>t.ParentViewModelID)
#Html.EditorFor(t=>t.Field1)
#Html.EditorFor(t=>t.Field2)
This all works well on initial page load, but I'm wondering how I should handle dynamically adding these partials via AJAX.
Suppose the user presses a button that's ultimately intended to add to one of these view model collections. I can AJAX back to the server, render the appropriate partial there, and return it to the client:
[System.Web.Mvc.HttpGet]
public ActionResult AddSubtype(int mainViewModelId)
{
var model = new Sub { ParentViewModelID=mainViewModelId};
return PartialView("MyPartial", model);
}
And then I use a bit of script to stick this into the DOM where it belongs:
success: (data) => { $('#subtypeHanger').append(data);},
This seems to work, except for one big part: when I evntually submit my form, I'm not seeing the data associated with this dynamically added partial in my view model.
I have been trying to debug this, but I'm wondering in broad terms whether this is possible- or alternately, how much MVC is supposed to abstract over such things. Obviously I can do things with JavaScript to force this to work. Is there an ASP.NET MVC pattern for this I should emulate, though?
EDIT: I'll mention some things I've tried since I posted this:
Managing the "name" and "id" attributes of the partial views' edit controls manually, so that they end up looking like they do when I nest these controls in the main view instead of a partial (i.e. longer, with more text and an index).
Using the main view model class for the partials. This makes me move the loops into the partial. The "name" and "id" property look like what I was going for in #1 above, but this design greatly complicates the process of returning the partial from my AJAX calls.
Using "for" loops instead of "foreach." By itself, this doesn't achieve what I want.
All this said, if #1 or #2 is the best pattern for what I'm doing, perhaps I can make that work.
"Situation: I have an ASP.NET Razor page that is constructed of partials."
This is called "Master Details"
check
Master Details CRUD with MVC 5 | The ASP.NET Forums
The trick is naming your Fields
#Html.HiddenFor(t=>t.ParentViewModelID ,new { htmlAttributes = new { #Name = "[" + i + "].ParentViewModelID" } })
#Html.EditorFor(t=>t.Field1 ,new { htmlAttributes = new { #Name = "[" + i + "].Field1" } })
#Html.EditorFor(t=>t.Field2 , new { htmlAttributes = new { #Name = "[" + i + "].Field2" } })
so it will be
<input type="text" name="[0].Field1" />
<input type="text" name="[0].Field2" />
<input type="text" name="[1].Field1" />
<input type="text" name="[1].Field2" />
and better(for ASP.NET mvc 5 Model Binding) if you use
public ActionResult Edit(MainViewModel master, List<Subtype> details)
if you provided the Full model i will provide a full working example
I'm trying to understand what the equivalent of a user control is within an MVC application? From what I understand, it's a Partial. The problem I'm finding is that when I use a user control, I'm able to encapsulate the logic within that control and re-use it across multiple pages without having to worry about the parent page.
How does this work with MVC? There doesn't seem to be any way to encapsulate logic with a partial view.. in fact it's confusing the hell out of me.
Does this mean that for any page that might use the partial, the controller would always have to return the data for the partial just in case it's required? Doesn't this seem incredibly inefficient? I can't seem to wrap my head around how this works...
You can add logic using razor syntax. For example, you can use conditional statements to manipulate the final output.
#{
if(whatever == true)
{
<p>Whatever is true</p>
}
else
{
<span id="someId">
<label for="enterName">Enter name:</label> <input type="text" id="enterName" />
</span>
}
}
In addition to this you can use #helper syntax like
#helper MakeLink(dynamic id)
{
<div id="actionButtons">
#Html.ActionLink("Some Title", "Some Action", new {id = id}) |
#Html.ActionLink("Another Title", "Another Action", "Some Controller", new {id = id})
</div>
}
The logic in partials is slightly different to what you are used to in Web Forms user controls. The above logic can be placed in a Partial so that you can reuse it later, you just need to place it in /Views/Shared/DisplayTemplates or EditorTemplates.
In the following code, the get action returns a betting card for a given race date, and the post I use the post action to transform properties of the bound model to route values for the get action.
Essential aspects of the Details View:
#using (Html.BeginForm("Upload", "BettingCard",
FormMethod.Post, new { id = "uploadForm", enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(true, "The upload was unsuccessful. The following error(s) occurred: ")
<div id="date-selector">
<div id="ymd">
#Html.LabelFor(model => model.RaceDate)
#Html.DropDownListFor(model => model.RaceDay, Model.YmdLists.Days)
#Html.DropDownListFor(model => model.RaceMonth, Model.YmdLists.Months)
#Html.DropDownListFor(model => model.RaceYear, Model.YmdLists.Years)
<input type="submit" value="Upload for this date" />
</div>
</div>
#Html.Telerik().Upload().Name("UploadedFiles")
}
Essential aspects of the controller code:
[HttpGet]
public ActionResult Details(int year, int month, int day) {
var model = new BettingCardModel
{
ResultMessage = "No betting card was located for the selected date."
};
DateTime passedDate;
if (!DateTimeHelper.TrySetDmy(year, month, day, out passedDate)) {
ModelState.AddModelError("", "One or more values do not represent a valid date.");
return View(model);
}
model.RaceDate = passedDate;
var bettingCard = _bettingCardService.GetByRaceDate(passedDate);
model.MapFromEntity(bettingCard);
return View(model);
}
[HttpPost]
public ActionResult Details(BettingCardModel model)
{
return RedirectToAction("Details", new { year = model.RaceYear, month = model.RaceMonth, day = model.RaceDay });
}
A good deal of the above code is experimental and diagnostic, so I'd like to avoid getting into a review of code that works, and rather concentrate on what I need to achieve. In the Details view I only need one 'command', being 'Display for Date', so I get off easily by using the submit button and the http post takes care of model binding. However, in the Upload view, I need two commands, being 'Display for Date' and 'Upload for Date', so I would like to make the 'Display for Date' operate strictly with the get actions, and only use a post action to submit an uploaded betting card for the date.
My problem is that when I make the 'Display for Date' command use an ActionLink instead of a submit, using model.RaceDay etc. as routing values, the URL parameters passed to Details all still contain their initial values, not values set by the user in the dropdowns. It seems the model binding code (whatever that may be) is not invoked for action links. What could I do here to avoid need a post just to do that binding?
I realise this probably not a direct model binding issue, but I don't know how else to express my question. When elements 'bound' to model properties are rendered, they have a bit more on their side than a simple input, say, and some basic styling, but something is 'built' around that input with lots of metadata. I would like some way to use that metadata to map to a URL when a get link on the page is clicked.
The problem you're having is that all of the model data and metadata is generated on the server dynamically and given to the client as static content. The binding is only aware of a change to the Model once it is submitted to the Server. All of that model metadata is static on the client side, using pure .NET it will have no way to know when a user changes a value in the drop-down to also change that value in a static anchor tag, which is what the ActionLink renders to. The answer is to use javascript. There are many many way to accomplish what you're trying to do through javascript. You could potentially write a custom HtmlHelper class to generate the javascript for you. However if you don't want to use javascript then you will HAVE to do a post to get the data the user selected to the Server.
If you're trying to avoid having to re-write code then you can create a partial view for the contents of the form and embed that in two separate views. Another thing you could try is to detect which button was pushed by having two submit buttons with the same name like so:
<input type="submit" name="command" value="Update" />
<input type="submit" name="command" value="Display" />
Then in your Controller in the [HttpPost] action you can detect which was pushed via the Request.Forms like this:
[HttpPost]
public ActionResult Details(BettingCardModel model)
{
if (Request.Forms["command"].Equals("Display"))
{
return RedirectToAction("Details", new { year = model.RaceYear, month = model.RaceMonth, day = model.RaceDay });
}
// Do your update code here...
return // Whatever it is you return for update.
}
hopefully this helps you.
ok so Im new to mvc. What Im making is a -create user form-. The UserViewModel has a branchcode property of type long. I want a small branch selector, where instead of a plain textbox for the code I have a textbox and a check name link, when clicked would return the name of the branch with some ajax.
So I made a branch selector and put it under Shared/EditorTemplates. Looks like this
#model long
<div class="editor-label">
Branch ID: #Html.TextBoxFor(model => model)
#Ajax.ActionLink("Get Branch Name", MVC.Admin.Home.BranchDetail(Model),
new AjaxOptions { UpdateTargetId = "BranchName", LoadingElementId = "loading" })
<p id="loading" style="display: none">
Loading...
</p>
</div>
<div id="BranchName" class="editor-field">
</div>
I have the UIHint setup in the viewmodel so when I say EditFor(model.BranchName) it shows up perfectly like this:
My problems:
1. There is no ajax! When I click it goes the the url : http://localhost:1159/Admin/Home/BranchDetail?brcd=0 And then the URL throws an error because there is no BranchDetailsView anywhere.
This is what the controller looks like:
public virtual ActionResult BranchDetail(long brcd)
{
if (Request.IsAjaxRequest())
{
//code to find branch
if (br == null)
{
return Content("No Branch Found");
}
else
{
return Content(br.BranchName + "Circle: " + br.Circle);
}
}
return View();//we should not be here.
}
2. Another problem is, how do I get the AjaxLink to return what code what typed. If you notice the screenie, the url to the link has brcd=0. I want to send over the branch code to the controller! I tried BeginRouteForm with an input button inside the editor, but that ends up submitting the entire Create page form? Would that be the right way to do this?
Note: Im using T4MVC, also, Initially I forgot but I did reference both microsoft.ajax.js and microsoft.mvc.ajax.js in the create page.
Update : I managed to get this working with JQuery and it seems pretty nice and simple. However, I would really like to know how this kind of thing would be generally done with Ajax.BeginForm since Im learning MVC.
Seems like you are using MVC 3, so you got to reference different scripts.
jquery-1.4.4.js
jquery.unobtrusive-ajax.js
to begin with
and it seems that there is no way to pass client side data to #Ajax.ActionLink
So you might jump straight to implementing your lookup with a little help of jQuery.
For some reason I'm stuck on this. I need to filter results from a View based on a DropDownList in the same view. The basic idea is this: I have a list of providers that belong to various partners, but the provider list contains ALL the providers together (for all partners). I need to be able to display the providers by partner when someone wants to see just that partner (otherwise, the default listing will be ALL providers). My view currently is the "default" (showing all), but for some reason Im sitting here staring at the monitor (for the last 2 hours!) trying to figure out how to filter these results.
Any suggestions where to start/how to do it?!
EDIT: If you want to do this with jQuery and AJAX (which will provide a better user experience because only the subdivisions list will refresh), see this tutorial.
If I understand correctly, you basically want to do a WebForms-style postback.
Let's say you have a control with countries and country subdivisions (e.g. states, provinces, etc). When the country changes, you want the appropriate subdivisions to display.
So this would be view:
<% using (Html.BeginForm()) { %>
<%=Html.DropDownList("Address.CountryId", new SelectList(Country.GetAll(), "Id", "Name"), new { onchange = "this.form.submit();" })%>
<%=Html.DropDownList("Address.CountrySubdivisionId", new SelectList(CountrySubDivision.GetByCountryId(Model.CountryId), "Id", "Name"))%>
<input type="submit" name="btnSubmit" value="Submit"/>
<%} %>
This is the key to getting the dependent list to filter:
new { onchange = "this.form.submit();" }
And in the controller, you'd have something like this:
[AcceptVerbs(HttpVerbs.Post)]
public ViewResult Index(string btnSubmit)
{
if (btnSubmit == null)
{
// return the view displayed upon GET
}
else
{
// process the submitted data
}
}
In the above code, if the form submission was triggered by changing the value in a dropdown, btnSubmit will be null. Thus, the action you are POSTing to can tell whether or not the user meant to finalize her changes.
To add upon the earlier answers.
To create a drop down (in ASP .NET MVC 3) I did the following:
Add code to Index.cshtml
#using (Html.BeginForm())
{
#Html.DropDownList("EmployeeId", (SelectList)ViewData["EmployeeId"])
<input type="submit" name="btnSubmit" value="Submit"/>
}
Add code to YourModelNameController.cs in the default ActionResult for Index()
public ActionResult Index()
{
//create a selectlist
var employeeList = from el in db.Employee select el;
ViewData["EmployeeId"] = new SelectList(employeeList, "EmployeeId", "TmName");
return View(modelName);
}
There are many ways to skin this cat. Here's one.
Enclose your DropDownList in a form with METHOD=GET.
<form action="" method="get">
<select name="provider">
<option>1</option>
<!-- etc -->
</select>
</form>
Then, in you controller, filter based on the value of provider that was passed in. Remember to treat it as a Nullable parameter so that you can have some kind of behavior when it's empty.
Without posting some of your current code, it's tough to get much more specific than that.
Let's assume that you're probably passing a model to the view and that model is a list or IEnummerable of partners. What you want to do is restrict the list. In order to do that add a drop down list in the view and fill it with some possible partners. This can be done either by putting a list in ViewData or expanding the model passed back to the view. Both have advantages. Now when you change the drop down reload the page but append a parameter which is the filter. In the controller check for that parameter in the action, if it isn't present then return an unfiltered list, if it is then apply a filter and return the list. The view will just dumbly display whatever you give it.
As for the filtering you might want to try using LINQ.
You probably want a parameter to your controller action, maybe a (nullable?) id of the provider, to filter the results already when you get them from DB. Then just use the same view to list them, and request a new list if the dropdownlist changes.
Best solution I know is that one.
http://gridmvc.codeplex.com/SourceControl/latest