Add additional fields in Umbraco membership profile - umbraco7

I am developing a site using Umbraco 7 where HomePage has a Signup form with several fields.
I have created a partial View using Register Member Template and call the Partial View on my HomePage.
Everything is working fine but i need to add some extra fields in the form(like Last name, Phone no., Address etc).
Is there any way to modify existing Member Profile Model to add these fields?
I am new to Umbraco so any help will be appreciated..

You'll want to add the properties to the membertype.
Mark them as editable:
Finally output them in your view:
for (var i = 0; i < registerModel.MemberProperties.Count; i++)
{
<div class="form-group">
<label for="#Html.IdFor(m => registerModel.MemberProperties[i].Value)">
#registerModel.MemberProperties[i].Name
#Html.HiddenFor(m => registerModel.MemberProperties[i].Alias)
</label>
#Html.EditorFor(m => registerModel.MemberProperties[i].Value, new { htmlAttributes = new { #class = "form-control" } })
</div>
}
Note: registerModel is of type Umbraco.Web.Models.RegisterModel
Also check out UmbracoIdentity, a great open source package that shows how to handle member related functionality

Related

partial views to get data and then post the results to save in database

I am very new to MVC, let me try to explain my scenario in plain simple English:
I have an strongly typed mvc form/page (Product.cshtml) with a model, say ProductViewModel.
This page has got two search buttons, one to search and bring the items to be added to the Product and other to bring in the location, most probably partial views.
Now, what I want is that these search results work in ajax form without complete post back, and then the results of these searches (items and location) should be posted back using model binding to the form when user clicks on the submit button.
What could be the best way of achieving this functionality?
Immediate responses will be well appreciated.
I thought, its good to share the complete code for clarity:
I have one form(Service1.chtml) that has a partial view to display users(_TestUser a partial view:read only), then another partial view(_PlotServiceRequestData) that should have a field to search the plot and bring back the details lke its owner name and landuser etc.
Then when I click on submit button of the main form, I should be able to read all data(main form) + new data from _PlotServiceRequestData partial view and save all data to database.
I was trying one more option, that is, to use #Ajax.ActionLink on Service1.cshtml to call the _GetPlotDetails method and then store partial view data in TempData, so that it is available to the form when users clicks on "Submit" button of Service1.cshtml, is this a right approach?, if I use ajax.BeginForm inside partial view then the data is posted to the
Service1 controller method which is actually to save the form data and not to update the partialview and in this method even I am not getting model data of the partial view.
Sevice1.cshtml:
#model ViewModels.TestViewModel
#{
ViewBag.Title =
"Service1";
}
#
using (Html.BeginForm())
{
#Html.LabelFor(m => m.Title)
#Html.EditorFor(m => m.Title)
#Html.Partial(
"_TestUser", Model)
<div id="RequestPlotData">
#Html.Partial(
"_PlotServiceRequestData", Model.requestData)
</div>
<button type="submit">Save Form</button>
}
#section Scripts {
}
_PlotServiceRequestData.cshtml:
===============================
#model ViewModels.PlotServicesRequestDataViewModel
<
div id="RequestPlotData">
#
using (Ajax.BeginForm("_GetPlotDetails", "Test", new AjaxOptions { UpdateTargetId = "RequestPlotData", Url = Url.Action("_GetPlotDetails","Test") }))
{
<h1>Request Details</h1>
 
<div>
#Html.LabelFor(m => m.plotAddress)
#Html.EditorFor(m => m.plotAddress)
<input type="submit" name="submit" value="Ajax Post" />
</div>
<div>
#Html.LabelFor(m => m.LandUser)
#Html.EditorFor(m => m.LandUser)
</div>
<div>
#Html.LabelFor(m => m.OwnerName)
#Html.EditorFor(m => m.OwnerName)
</div>
}
</
div>
CONTROLLER:
==========
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Web;
using
System.Web.Mvc;
namespace
TestNameSpace
{
public class TestController : Controller
{
//
// GET: /Test/
public ActionResult Service1()
{
Injazat.AM.mServices.
LocalDBEntities context = new Injazat.AM.mServices.LocalDBEntities();
TestViewModel model =
new TestViewModel() { user = context.Users.First(), Title = "Land Setting Out",
requestData =
new PlotServicesRequestDataViewModel() { ServiceNumber ="122345", TransactionDate="10/10/2033" } };
return View(model);
}
[
HttpPost()]
public ActionResult Service1(TestViewModel model)
{
PlotServicesRequestDataViewModel s = (PlotServicesRequestDataViewModel)TempData[
"Data"];
TestViewModel vm =
new TestViewModel() { user = model.user, requestData = s, Title = model.Title };
return View(vm);
 
}
[
HttpGet()]
//public PartialViewResult _GetPlotDetails(string add)
public PartialViewResult _GetPlotDetails(PlotServicesRequestDataViewModel requestData)
{
//PlotServicesRequestDataViewModel requestData = new PlotServicesRequestDataViewModel() { plotAddress = add};
requestData.OwnerName =
"owner";
requestData.LandUser =
"landuser";
TempData[
"Data"] = requestData;
return PartialView("_PlotServiceRequestData", requestData);
}
}
}
You can probably use the jQuery Form plugin for this. This makes the process of posting the data from your form back to the server very easy. The form would post to an action that would return a partial view that you can then push into your UI.
To make this easier, jQuery form actually has a "target" option where it will automatically update with the server response (ie. the partial view returned from your search action).
View
<form id="searchForm" action="#(Url.Action("Search"))" method="POST">
<input name="query" type="text" /> <!-- order use Html.TextBoxFor() here -->
<input type="submit" />
</form>
<div id="result"><!--result here--></div>
Javascript
$('#searchForm').ajaxForm({
target: '#result'
});
Controller
public ActionResult Search(string query)
{
// Do something with query
var model = GetSearchResults(query);
return Partial("SearchResults", model)
}
This should hopefully help you to get on the right track. jQuery Form is a good plugin and is the main thing you should look into for ajaxifying your form posts back to the server. You might also want to look into using jQuery's $.post and $.ajax functions, but these require slightly more work.

Validation of DropDownListFor is not working in MVC3?

Validation is Working on Other Input type text element but not working on DropDownListFor
Class Purchase Input Property Code
[Required]
public string LedgerId { get; set; }
Class View Model Code
PurchaseViewModel purchaseVM = new PurchaseViewModel
{
// PurchaseInput=purchaseInput,
Ledger = uw.LedgerRepository.Get().Select(x => new SelectListItem { Value = x.Id.ToString(), Text = x.LedgerName }),
};
View
<div class="column">
<div class="labelField">
#Html.LabelFor(model => model.PurchaseInput.LedgerId, "Party")
</div>
<div class="ItemField">
#Html.DropDownListFor(model => model.PurchaseInput.LedgerId, new SelectList(Model.Ledger, "Value", "Text"))
#Html.ValidationMessageFor(model => model.PurchaseInput.LedgerId)
</div>
</div>
On the face of it, it seems that you do not have an empty item in your select list. The validation will only trigger if the user selects a dropdown item with string length of zero. If you examine the Html source can you see the validation attributes on the dropdown ( depending on whether you are using unobtrusive validation or not)?
Yes, there are problems with validation of DropDownListFor. look at this link. They get validation data manually from metadata - http://forums.asp.net/t/1649193.aspx
Although this is a workaround, at least it fires some sort of validation. Try:
#Html.DropDownListFor(model => model.PurchaseInput.LedgerId, new SelectList(Model.Ledger, "Value", "Text"), new { #class = "required" })

Setting authorization on a specific ASP .NET MVC 3 field?

Is it possible to set authorization on a specific field in MVC 3?
My initial thought (and MSDN research) indicates that the [Authorize] tag is only for controller level actions (create,edit,index,etc). I can do this on the controller action:
[Authorize(Roles = "RoleA,RoleB")]
public ActionResult Create()
{
return View(new Tracking());
}
The scenario is that two roles (RoleA and RoleB) can access the 'Edit' controller. But only RoleA can change the first field. The other role (B) can only view the field.
I would like to do something like this on a specific field:
[Required]
[Range(1, 99)]
[Authorize(Roles = "RoleA")]
public int Sequence { get; set; }
UPDATE1:
A little more research down the StackOverflow rabbit roles reveals that I need to use partial views.
So in my view I add this code:
<div>
#if (Context.User.IsInRole("RoleA"))
{
#Html.Partial("_SequenceEdit")
}
else
{
#Html.Partial("_SequenceView")
}
</div>
So if the user is RoleA they get a partial view that allows editing of the 'sequence' field. Otherwise they get a view only of the 'sequence' field.
My view only partial view looks like this:
<div class="editor-label">
#Html.LabelFor(model => model.Sequence)
</div>
<div class="editor-field">
#Html.DisplayFor(model => model.Sequence)
#Html.HiddenFor(model => model.Sequence)
#Html.ValidationMessageFor(model => model.Sequence)
</div>
I see that you've already figured out how to modify the view in order to not show a text box to users in Role B. But you should also do server-side validation to make sure only users in Role A can edit the field.
[Authorize(Roles = "RoleA,RoleB")]
[HttpPost]
public ActionResult Edit(int trackingID, Tracking newTrackingObject)
{
// grab the current version of the tracking object from your data repo
var oldTrackingObject = trackingRepo.GetByID(trackingID);
// check if the user is in role A and edit the sequence number
if(Context.User.IsInRole("RoleA"))
oldTrackingObject.Sequence = newTrackingObject.Sequence;
// continue processing the new tracking object
// after all processing is done, persist the edited tracking object back to the repo
trackingRepo.Update(oldTrackingObject);
trackingRepo.SaveChanges();
}
This will prevent users in Role B from changing the sequence field by manually editing the hidden form field (eg. with FireBug or a similar tool.)

ASP.NET MVC 3 #Html.DropDownListFor ignoring selectedValue

In my asp.net MVC 3 project I would like to create a contact that's related to a company.
You can either directly create a contact OR go via the company details view and add a new contact passing the companyId to set that company already in the dropdown on the contact create form.
The problem is that I can 't get the passed company as default in my dropdown.
Global.asax
routes.MapRoute("contactCreate", "contact/toevoegen/{companyid}", new { action = "ContactCreate", controller = "Backend", companyid = UrlParameter.Optional });
Controller method
public ActionResult ContactCreate(int? companyid)
{
Contact contact = new Contact();
ViewBag.StatusList = srep.getContactStatusses();
ViewBag.CompanyId = companyid;
return View(contact);
}
View
#model xxx.Models.Contact
...
<div class="editor-label">
#Html.LabelFor(model => model.bedrijf_id)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.bedrijf_id, new SelectList(ViewBag.Bedrijven, "bedrijf_id", "bedrijf_naam",ViewBag.CompanyId), "--Kies bedrijf--")
#ViewBag.CompanyId
#Html.ValidationMessageFor(model => model.bedrijf_id)
</div>
...
#ViewBag.CompanyId has a value.
Any idea why it's not setting the selected value?
When doing a "DropDownListFor" it will try to match up the value passed in from the model for the selected value. So in your example it will use "bedrijf_id" as the selected value. It looks like you want the selected value to be from something outside of your model.
From the comments I think what you want is just a DropDownList as follows:
#Html.DropDownList("DropDownList", new SelectList((ViewBag.Bedrijven, "bedrijf_id", "bedrijf_naam", ViewBag.CompanyId), "--Kies bedrijf--")
Hope this helps.

ASP.NET MVC 3 - Validation Question

Good evening everyone I have a question regarding validation of drop-down list values. I have a view that is bound to a view model type called ReservationData.
This object contains a property CustomerVehicles of type List<VehicleData>. VehicleData has two int properties VehicleMakeId and VehicleModelId.
On my view I am trying to loop over the number of items in the CustomerVehicles collection and displaying two dropdowns for each, a vehicle make dropdown and a vehicle model dropdown using DropDownListFor.
When I try to submit and validate I do not see any validation errors displayed on the screen.
Just in case you are wondering I have added a ValidationMessageFor for each dropdown as well. I am not sure if this is an issue with the structure of my view model and its complexity and how the controls need to be named or how the ids need to be set. Any help would be greatly appreciated.
Here is the code for the looping over the collection:
#for (var i = 0; i < Model.CustomerVehicles.Count(); i++)
{
var vehicleNumber = i + 1;
<div class="vehicle-selection-wrapper">
<div class="content-container">
<h3>
Vehicle #vehicleNumber</h3>
<img class="vehicle-image" alt="manufacturer image" src="#Url.Content("~/Content/images/default-vehicle.gif")" /><br />
#Html.LabelFor(m => m.CustomerVehicles[i].VehicleMakeId)
#Html.DropDownListFor(m => m.CustomerVehicles[i].VehicleMakeId
, new SelectList(Model.VehicleMakes, "Id", "Name")
, #UIDisplay.Dropdown_DefaultOption, new { #class = "long-field" })<br />
#Html.ValidationMessageFor(m => m.CustomerVehicles[i].VehicleMakeId)<br />
#Html.LabelFor(m => m.CustomerVehicles[i].VehicleModelId)
#Html.DropDownListFor(m => m.CustomerVehicles[i].VehicleModelId
, new SelectList(new List<CWR.Domain.VehicleModel>(), "Id", "Name")
, #UIDisplay.Dropdown_DefaultOption, new { #class = "long-field" })
#Html.ValidationMessageFor(m => m.CustomerVehicles[i].VehicleModelId)
</div>
</div>
}
Ok so I also noticed that in the generated HTML the selects that are generated are missing the HTML5 data-val attributes that are associated to elements to handle validation. Here is the generated HTML
<select class="long-field" id="CustomerVehicles_0__VehicleMakeId" name="CustomerVehicles[0].VehicleMakeId"><option value="">-- Select --</option>
</select><br />
<span class="field-validation-valid" data-valmsg- for="CustomerVehicles[0].VehicleMakeId" data-valmsg-replace="true"></span><br />
<label for="CustomerVehicles_0__VehicleModelId">Model</label>
<select class="long-field" id="CustomerVehicles_0__VehicleModelId" name="CustomerVehicles[0].VehicleModelId"><option value="">-- Select --</option>
</select>
<span class="field-validation-valid" data-valmsg-for="CustomerVehicles[0].VehicleModelId" data-valmsg-replace="true"></span>
Additionally in my VehicleData class the VehicleMakeId and VehicleModelId properties are decorated with a Required attribute.
UPDATE:
Ok so I was testing and noticed that if I keep my code identical except I swap the Html.DropdownListFor calls with Html.TextboxFor calls then the validation works. What could be causing this? Could it be a framework bug with the unobtrusive validation?
UPDATE: Contains Fix
So after posting this same question on the ASP.NET Forums, I was able to get a solution. In the post you will be able to see that there is a bug in the unobtrusive validation framework and how it handles validation of dropdownlists. The user counsellorben does a good job in explaining the problem as well as a solution (including sample code) that will assist others in avoiding this issue in the future, or at least until Microsoft builds in a fix in to the framework.
Thank you everyone for your assistance.
I too have come across this obviously massive oversight regarding client side validation with dropdownlists in MVC 3 and the best solution I can offer is to put the missing HMTL attributes in yourself.
In your view model create a property like this.
public Dictionary<string, object> CustomerVechicleAttributes
{
get
{
Dictionary<string, object> d = new Dictionary<string, object>();
d.Add("data-val", "true");
d.Add("data-val-required", "Please select a Vechicle.");
return d;
}
}
Then in your code, enter
#Html.DropDownListFor(m => m.CustomerVehicles[i].VehicleMakeId
, new SelectList(Model.VehicleMakes, "Id", "Name")
, #UIDisplay.Dropdown_DefaultOption,
**Model.CustomerVechicleAttributes** })
Just add the Model.CustomerVechicleAttributes as htmlAttributes to your dropdownlist.
This will inject the necessary attributes that are missing. You will of course need to add any other attributes you may need like your class attribute.
Hope this helps.
This is the simpliest way I found to do it, just adding data-val-*-* attributes in HtmlAttributes of DropDownListFor, inside the view. The following method works with RemoteValidation too, if you do not need remote validation, simply remove the elements containing data-val-remote-*:
#Html.DropDownListFor(m => m.yourlistID, (IEnumerable<SelectListItem>)ViewBag.YourListID, String.Empty,
new Dictionary<string, object>() { { "data-val", "true" },
{ "data-val-remote-url", "/Validation/yourremoteval" },
{ "data-val-remote-type", "POST" }, { "data-val-remote-additionalfield", "youradditionalfieldtovalidate" } })
I hope it may help. Best Regards!
you should try to add data annotations on your view model properties first so you could see the validation messages.
you might find what you need here
http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx
or create custom ones if needed.
what exactly do you need to validate?
I had exactly the same problem with the field getting correctly validated in TextBoxFor but not in DropDownListFor.
#Html.DropDownListFor(m => m.PaymentTO.CreditCardType, Model.CreditCardTypeList, "Select Card Type", new { style = "width:150px;" })
Since I had another DropDownListFor working on the same page, I knew that it wasn’t a generic DropDownListFor problem. I also have a complex model and parent object PaymentTO wasn’t initialized. When I set viewTO.PaymentTO = new PaymentTO(); in the Controller, the validation for the DropDownListFor started to work. So there is probably a problem with DropDownListFor, but the fix can be as simple as initializing the object in the controller.

Resources