About asp.net mvc model binding and its parameters - asp.net-mvc-3

Here is view models
public class ArticleViewModel
{
public string ID { get; set; }
public string Title{ get; set; }
public string Body { get; set; }
public List<BETag> TagsList { get; set; }
}
public class BETag
{
public string ID { get; set; }
public string Name { get; set; }
}
An action
[HttpPost, AuthorizeEx]
public ActionResult AddArticle(ArticleViewModel articleViewModel)
{
//articleViewModel.Tags.Count == 0
//Request.Form["TagsList"] == "tag1, tag2..."
}
and a part of AddArticle.cshtml
#Html.TextAreaFor(m => m.TagsList )
My question is why articleViewModel.Tags.Count is equal 0, but
Request.Form["TagsList"] is equal "tag1, tag2..."? How to bind ArticleViewModel properly?

Lists don't work that way in MVC. You need to use something like EditorFor(m => m.TagsList) and then you need to create a BETag EditorTemplate. But that's only part of the problem, and really won't work for you either.
What you really want is just a simple string that takes your list of tags, such as
public string TagListString {get;set;}
Then, in your controller, you parse the string and extract all your tags, then add them to the TagsList.
var tags = TagListString.Split(' '); // assumes only single space between tags,
// you should add more filtering to make sure
foreach(var tag in tags) {
TagList.Add(new BETag() { Name = tag });
}
MVC works with single items, not complex types. There is some built-in processing to breakdown complex types in some cases, and to automatically iterate over collections, but those don't work in your case because you want to edit all the items in a single field. So your only option is to parse the field in the post method and put the data where you want it.

Related

how to return multiple variable with jsonresult in mvc from controller to view?

in below code, i pass two parameters one is a list and second is viewbag message, but in view, side can't use viewbag.
So how to use it, please anyone help me
in view
where to i place viewbag message
create custom class
private class LineData
{
public string y { get; set; }
public string item1 { get; set; }
public string name { get; set; }
public string message { get; set; }
public List<LineData> list { get; set; }
}
In controller side
In view
As far as I understand to your question, you should create new class that holds both your list and message (instead of passing that to ViewBag).
public class YourResponse
{
public string Message { get; set; }
public List<SomeContent> Content { get; set; }
}
Then in your action in controller, create a new instance of this class and fill in the values and pass this instance back to the client.
public ActionResult YourActionName()
{
// do the stuff here to get message and list
var response = new YourResponse
{
Message = message, //insert your message here
Content = list //and list of data here
}
return Json(response);
}
And finally read and use the data from server within client code.
function OnSuccessed(data)
{
var message = data.Message;
var list = data.Content;
// you can work with message and list here
}
Just note that this is raw example, I have not run the code.

Is there something like [Bind(Exclude="Property")] for asp.net web api?

I'm trying to exclude a property from my Post Action in a web api controller, is there something like [Bind(Exclude="Property")] for asp.net web api?
This is my model:
public class ItemModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
I want to exclude the Id in the Post Action, because it is autogenerated, but I need to return it in my Get Action.
I Know I could have two models, one for my Post action and one for my Get action, but I'm trying to do this with just one model.
I would favour mapping models but this could be achieved by checking if the request is a POST in a ShouldSerialize method:
public class MyModel
{
public string MyProperty1 { get; set; }
public string MyProperty2 { get; set; }
public bool ShouldSerializeMyProperty2()
{
var request = HttpContext.Current.Request;
if (request.RequestType == "POST") return false;
return true;
}
}
Where your method name is the name of the property prefixed with ShouldSerialize.
Note this will work for JSON. For XML, you will need to add the following line to your config:
config.Formatters.XmlFormatter.UseXmlSerializer = true;
You can simply create a DTO for POST.

asp.net mvc 3 razor get one element from IEnumerable

I my view model(LIST) looks like this:
public class ConversationModel
{
public int ID { get; set; }
public string Body { get; set; }
public DateTime Datetime { get; set; }
public string Username { get; set; }
public string ImgUrl { get; set; }
public string ToUserID{ get; set; }
}
this is my view
#model IEnumerable<NGGmvc.Models.ConversationModel>
how i can get ToUserID on current postion? something like this
#Model[0].ToUserID
Thanks
You should be able to do:
#Model.First().ToUserID
Note, you may want to check whether there are any items in the enumerable first as if there aren't, then First() will return null
(Note, because you had #Model[0] in your question, I assume you are specifically trying to get the first value. I may have the wrong end of the stick, in which case Jakub's answer should sort you out!)
You should be able to use the following:
#Model.First().ToUserID
However, if your model will only ever reference the first element of the enumeration in the view, I would recommend that you only pass that element to the view.
For example:
#model ConversationModel
#Model.ToUserID
And in the controller only pass the first element that is required:
List<ConversationModel> conversationList = //your conversation model initialisation code
return View(conversationList.First());
#foreach(var model in Model)
{
#model.ToUserID
}

MVC3 Dynamic DataAnnotation attribute StringLength

UPDATE #3: Entire question
I have a class HB:
public class HB
{
public int Id { get; set; }
[StringLength(3000)]
public string Text { get; set; }
public Title Title { get; set; }
}
And Title:
public class Title
{
public int Id { get; set; }
public string Name { get; set; }
public int MaxChar { get; set; }
}
Before you can write a HB (which is kind of an article), you have to choose your title, so your StringLength for HB.Text can be determined. Meaning, this article can only have a certain amount of chars, deppending on what 'Title' the writer has. Example: Title1 can only write a 'HB' with 1000 chars, and Title2 can write a 'HB' with 3000 chars. So. Thats means the the StringLength has to come from Title.MaxChar. Whats the smartest way to do that?
The Title entity is prefixed data that will be stored in the db.
To be crystal clear, what I want to achieve is something in the line with: [StringLength(Title.MaxChar)]
Ive done structure/design for this mechanism in Webforms a million times, my brain just cant addapt to mvc, so some help would be appreciated. Code would be even more appreciated.
Pretty sure that is not possible as written. This strikes me as trying to force business logic into the model that belongs in the controller.
In this situation, I would make the attribute on the Text property [StringLength(3000)]. In the controller, during validation, I would write something along these lines:
public ActionResult (HB model)
{
if (model.Text.Length > model.Title.MaxChar){
ModelState.AddModelError("Text", string.Format("Text for this Title cannot exceed {0} characters.", model.Title.MaxChar));
}
if (ModelState.IsValid)
{
//do stuff
return RedirectToAction("Index"); //or something
}
else
{
return View(model);
}
}
I believe this will accomplish what you are trying to do. Now, for the Title object, I'd flatten that out a bit in your model:
public class HB
{
#region Base Properties
public int Id { get; set; }
[StringLength(3000)]
public string Text { get; set; }
#endregion
#region Title Properties
public int TitleId { get; set; }
public string TitleName { get; set; }
public int TitleMaxChar { get; set; }
#endregion
}
This is assuming you need to display that information in your view. If you just need to reference it for your business logic validation, just have the TitleId property and use that to instantiate the Title object in your controller when you need it. Don't forget to make hidden inputs for each of these properties if they are not editable!

MVC3 Razor > Make Model IEnumerable, so it can be used in View?

I have this model:
namespace easyBooking.Models
{
public class CardInfo
{
public string name { get; set; }
public string adress { get; set; }
public string zipcode { get; set; }
public string city { get; set; }
public string ccsID { get; set; }
public string birthday { get; set; }
public string nationalitet { get; set; }
public string cardType { get; set; }
}
}
which I populate from a function and return to the controller. The problem is that I cannot hand this model to my view, since it does not implement IEnumerable... Instead I have to add information to the viewBag like this:
var cardInfo = FunctionLib.cardCampingPas(myArray);
ViewData.Add("name", cardInfo.name);
ViewData.Add("adress", cardInfo.adress);
ViewData.Add("nationalitet", cardInfo.nationalitet);
ViewData.Add("ccsID", cardInfo.ccsID);
ViewData.Add("zipcode", cardInfo.zipcode);
ViewData.Add("city", cardInfo.city);
ViewData.Add("cardType", cardInfo.cardType);
return View("../Reservation/New", ViewData);
which is kind of stupid, when I should be able to just add the cardInfo model directly to the View.
var cardInfo = FunctionLib.cardCampingPas(myArray);
return View("../Reservation/New", cardInfo);
So basically I just need to pass a bunch of strings to the view. How can my model CardInfo be accessed directly from my view?
Update
#rene - view data where I added a #model declaration. I did get some errors when I tried it last, but it must have been because I tried to foreach it or something.. now... just no error, and I have no idea if anything is passed to the view or how to get the data.
#model easyBooking.Models.CardInfo
#{
ViewBag.Title = "New";
}
<h2>Ny reservation</h2>
<p>Benyttet kort: #Model.cardType</p>
This now works...
You can pass your collection directly to the view.
In the view, you'll need to declare the model type:
#model IEnumerable<CardInfo>

Resources