I am not sure why am i getting sequence contains no elements im kinda new mvc
My Controller
[HttpPost]
public ActionResult DeleteAnnounce(string announce)
{
using (var db = new HarmonyMainServerDbContext())
{
ANNOUNCEMENT annoude = db.Announcer.First(c => c.AnnounceTitle == announce);
db.Announcer.Remove(annoude);
db.SaveChanges();
}
return RedirectToAction("ViewAnnounce");
}
My View
<div id="clientDetailsContainer">
#using (Html.BeginForm("Announcements", "Admin", FormMethod.Post, new { id = "Announcers" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="module-controls" style="display:block;">
<img src="../Images/src/back.png"/><span>Back to List</span>
<a class="k-button module-action" id="submitSave" title="haha"><img src="../Images/src/subgrid_save.png"/><span>Save</span></a>
<a class="k-button module-action" id="submitDelete" ><img src="../Images/src/subgrid_save.png"/><span>Delete</span></a>
</div>
<h2>Announcement</h2>
#Html.HiddenFor(model => model.AnnounceID)
<div class="client-details" style="margin-left: 50px">
<p>
<label class="label-ant">Announcement Title</label>
#Html.TextBoxFor(model => model.AnnounceTitle, new {#class="k-textbox", #style="width:250px" })
#Html.ValidationMessageFor(model => model.AnnounceTitle)
</p>
<p>
<label class="label-ant">Announcement Remarks</label>
#Html.TextBoxFor(model => model.AnnounceRemarks, new {#class="k-textbox", #style="width:250px" })
#Html.ValidationMessageFor(model => model.AnnounceRemarks)
</p>
<p>
<label class="label-ant">Announce Link</label>
#Html.TextBoxFor(model => model.AnnounceLink, new {#class="k-textbox", #style="width:250px" })
#Html.ValidationMessageFor(model => model.AnnounceLink)
</p>
</div>
}
<script>
$("#submitSave").click(function () {
$("#Announcers").submit();
});
$("#submitDelete").click(function () {
$("#Announcers").attr({
"action" : "/Admin/DeleteAnnounce",
});
});
</script>
</div>
In collection there is few methods which you need to understand difference
First - means that if nothing is returned it will throw exception,
but it allows collection to have more than first
Single - means get only one item, so if collection match more than
one or non you will get exception, this is kind "constraint"
FirstOrDefault - means that collection can have more than one or none items matching
SingleOrDefault - collection should have only one or non items matching items
It's because you're using First(). This throws the exception if there's no Announcer with matching title.
See https://msdn.microsoft.com/library/bb291976%28v=vs.100%29.aspx
Related
Have been trying to get a member profile management area working with ajax as each section of the page is hidden within a show hide div.
I have used ajax before in MVC applications but have never used it with umbraco surface controllers before. I'm unsure why returning a partial view in the controller is outputting the whole page and not just the partial view that I am giving to it.
Controller:
[HttpPost]
[ActionName("MvcMemberEditProfileDetails")]
public ActionResult MvcMemberEditProfileDetails(MvcMemberEditProfileDetailsModel model)
{
var memberService = Services.MemberService;
var currentUser = Membership.GetUser();
var member = memberService.GetByEmail(currentUser.Email);
bool result = false;
if (ModelState.IsValid)
{
...
}
if (result)
{
...
}
return PartialView("MvcMemberEditProfileDetails", model);
}
View:
#model Umbraco714.Models.MvcMemberEditProfileDetailsModel
#using (Ajax.BeginForm("MvcMemberEditProfileDetails", "MvcMember", new AjaxOptions() { HttpMethod = "POST", UpdateTargetId = "MvcMemberEditProfileDetails", InsertionMode = InsertionMode.Replace }))
{
if (Model.Result != null)
{
if (Model.Result == true)
{
<div id="result" class="alert alert-success">
#Html.Raw(Model.ResultMessage)
</div>
}
else
{
<div id="result" class="alert alert-danger">
#Html.Raw(Model.ResultMessage)
</div>
}
}
<div class="form-default">
<div class="row">
<div class="col-md-6">
<div class="form-group">
#Html.LabelFor(m => m.FirstName)
#Html.TextBoxFor(m => m.FirstName)
#Html.ValidationMessageFor(m => m.FirstName)
</div>
</div>
<div class="col-md-6">
<div class="form-group">
#Html.LabelFor(m => m.LastName)
#Html.TextBoxFor(m => m.LastName)
#Html.ValidationMessageFor(m => m.LastName)
</div>
</div>
<div class="col-md-6">
<div class="form-group">
#Html.LabelFor(m => m.CompanyName)
#Html.TextBoxFor(m => m.CompanyName)
#Html.ValidationMessageFor(m => m.CompanyName)
</div>
</div>
<div class="col-md-6">
<div class="form-group">
#Html.LabelFor(m => m.CompanyPosition)
#Html.TextBoxFor(m => m.CompanyPosition)
#Html.ValidationMessageFor(m => m.CompanyPosition)
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
#Html.LabelFor(m => m.CompanyBio)
<span class="bs-tooltip" data-toggle="tooltip" data-placement="top" title="Max 1000 characters long"><i class="fa fa-info-circle" aria-hidden="true"></i></span>
#Html.TextAreaFor(m => m.CompanyBio, new { #rows = "4", #maxlength = "1000" })
#Html.ValidationMessageFor(m => m.CompanyBio)
</div>
#TempData["Status"]
<div class="form-group nomargin">
<div class="text-right">
<button class="button" type="submit"><i class="fa fa-floppy-o" aria-hidden="true"></i> Update</button>
</div>
</div>
</div>
</div>
</div>
}
I have everything that needs to be included (as far as I'm aware) well before the form and there are no console errors.
<script src="/scripts/jquery.js"></script>
<script src="/scripts/bootstrap.min.js"></script>
<script src="/scripts/jquery-val.js"></script>
<script src="/scripts/jquery.unobtrusive-ajax.min.js"></script>
I have also made sure that UnobtrusiveJavaScriptEnabled is set to true in the web.config but I'm still getting a full page rendered when I post the form.
Initially:
When the page loads and the form shows
After:
When the form is submitted and the correct partial view is returned but inside of an entire
Feeling pretty dumbfounded that I've spent more that a couple of hours looking into this even though it's clearly working in a sort of way.
Is it possible / a known thing for this to happen? I searched around but couldn't find any topics with a similar issue, unless I was just wording things wrong.
Just looking for a nudge in the right direction if anybody has any ideas?
Umbraco can be funny with partials. Try returning CurrentUmbracoPage() in the controller.
As for the message, you could use TempData as it only lasts for one request, rather than the model.
ViewBag.cliente_id = new SelectList(db.cliente.Where(c => c.status_ativacao == 1), "id", "nome", manutencao.cliente_id);
It Still are returning all clients.
I need to return just who column 'status_ativacao' = value 1.
Am I sure doing this here or I need to do it on dropdownlist?
View:
<div class="form-group">
<label class="col-sm-2 control-label" for="cliente_id">Cliente</label>
<div class="col-md-6">
#Html.DropDownList("cliente_id", (SelectList)ViewBag.Values, new { onchange = "this.form.submit();" })
#Html.ValidationMessageFor(model => model.cliente_id)
<!-- <input type="submit" value="Atualizar Cliente" class="btn btn-default"/> -->
</div>
You have to convert that query into a list first, like this:
ViewBag.cliente_id = new SelectList(db.cliente.Where(c => c.status_ativacao == 1).ToList(), "id", "nome", manutencao.cliente_id);
Also, change the Html.DropDownList in your view, like this:
#Html.DropDownList("cliente_id", (SelectList)ViewBag.cliente_id, new { onchange = "this.form.submit();" })
I have a form with and one of the fields for the model is complex, so I created a custom editor for that field.
Here is the part of the editor in the main form:
<div class="form-group">
<label class="col-md-3 control-label">#i18n.Translations</label>
<div class="control-group col-md-9">
#Html.EditorFor(m => m.Translations)
</div>
</div>
Here is the Custom Editor:
#using XXX.i18n
#using XXX.ViewModels
#model XXX.ViewModels.ServiceTranslation
#{
bool translationNameValid = Html.ViewData.ModelState.IsValidField(Html.IdFor(m => m.TranslationName).ToString());
bool translationDescriptionValid = Html.ViewData.ModelState.IsValidField(Html.IdFor(m => m.TranslationDescription).ToString());
}
<div class="form-group">
#Html.HiddenFor(m => m.EntityLanguageId)
#Html.HiddenFor(m => m.Language)
#Html.HiddenFor(m => m.TranslationId.Left)
#Html.HiddenFor(m => m.TranslationId.Right)
<div class="col-md-6">
<div class="input-group #(translationNameValid ? null : "state-error")">
<span class="input-group-addon">#Model.Language</span>
#Html.TextBoxFor(m => m.TranslationName, new { #placeholder = i18n.Name, #class = "form-control" })
</div>
<div class="#(translationNameValid ? null : "state-error")">
<em for="#Html.IdFor(m => m.TranslationName)" class="invalid">#Html.ValidationMessage("TranslationName")</em>
</div>
</div>
<div class="col-md-6 #(translationDescriptionValid ? null : "state-error")">
#Html.TextBoxFor(m => m.TranslationDescription, new { #placeholder = i18n.Description, #class = "form-control" })
<em for="#Html.IdFor(m => m.TranslationDescription)" class="invalid">#Html.ValidationMessage("TranslationDescription")</em>
</div>
</div>
Also, I should mention that the main form is inside a partial and the TranslationName and TranslationDescription are 2 required fields (and are annotated with [Required] in the ViewModel)
The #Html.ValidationMessage return the required field message with the textboxes are empty.
My problem is that the translationDescriptionValid and the translationNameValid are always true and they should return false when the fields are blank.
I've used this method in other forms with success.
What am I doing wrong here?
New new to C# and MVC, so apologies in advance for posting something which is probably obvious.I have looked at similar answers but still can't see how and what value in the RadioButtonFor should be used so that it can be POSTed back to the controller.
Controller
[HttpPost]
public ActionResult Score(ExamViewModel exam)
{
const int AddCorrect = 1;
var correct = from c in db.Answers
where c.ID == 1
select c.CorrectAnswer;
if (ModelState.IsValid)
{
if (correct == exam.CorrectAnswer)
{
ViewData["message"] = "Correct Answer!";
return View("Results");
}
else
{
var feedback = from g in db.Questions
where g.ID == 1
select g.GrammarPoint;
ViewData["message"] = "That's not the right answer.";
ViewData["feedback"] = feedback;
return View("Results");
}
}
return View("Results");
And the View
#model AccessEsol.Models.ExamViewModel
#{
ViewBag.Title = "TakeTest";
}
<h2>TakeTest</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<div class="display-label">
<h3>Click the correct answer:</h3>
</div>
<div class="display-field">
<strong>#Html.DisplayFor(model => model.Text.Text )</strong>
</div>
#Html.DisplayFor(model => model.Foil1.Foil1)
#Html.RadioButtonFor(model =>model.Foil1, "Incorrect" )
#Html.DisplayFor(model => model.Foil2.Foil2)
#Html.RadioButtonFor(model => model.Foil2, "Incorrect" )
#Html.DisplayFor(model => model.Foil3.Foil3)
#Html.RadioButtonFor(model => model.Foil3, "Incorrect")
#Html.DisplayFor(model => model.CorrectAnswer.CorrectAnswer)
#Html.RadioButtonFor(model => model.CorrectAnswer, "Correct")
<p>
<input type="submit" value="Submit Answers" />
</p>
</fieldset>
}
I also tried to pass a string from the CorrectAnswer into the Score Controller without success.Much appreciated if you can point to how can checked RadioButton value can be passed back to the Controller?
You should not have 3 different properties but instead a single one that will contain the answer. This will allow you to group the radio buttons and be able to select only one of them:
#model AccessEsol.Models.ExamViewModel
#{
ViewBag.Title = "TakeTest";
}
<h2>TakeTest</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<div class="display-label">
<h3>Click the correct answer:</h3>
</div>
<div class="display-field">
<strong>#Html.DisplayFor(model => model.Text.Text)</strong>
</div>
#Html.DisplayFor(model => model.Foil1.Foil1)
#Html.RadioButtonFor(model => model.Answer, "1")
#Html.DisplayFor(model => model.Foil2.Foil2)
#Html.RadioButtonFor(model => model.Answer, "2")
#Html.DisplayFor(model => model.Foil3.Foil3)
#Html.RadioButtonFor(model => model.Answer, "3")
#Html.DisplayFor(model => model.CorrectAnswer.CorrectAnswer)
#Html.RadioButtonFor(model => model.Answer, "4")
<p>
<input type="submit" value="Submit Answers" />
</p>
</fieldset>
}
and then in your controller action check if the Answer property value that is sent is the correct one for this question. As you can see from the view we have multiple answer for the question and the value is what will get sent to the server. Usually you will use the ID of the answer as value and on the server you can compare whether this is the correct answer for the question.
i have added extra three input fields to my view to enable the system admin to submit four objects at the same time instead of one object at a time; the view looks as the following:-
#model Elearning.Models.Answer
#{
ViewBag.Title = "Create";
}
<div id = "partialWrapper">
#using (Ajax.BeginForm("Create", "Answer", new AjaxOptions
{
HttpMethod = "Post",
InsertionMode = InsertionMode.InsertAfter,
UpdateTargetId = "incrementanswer",
OnSuccess = "removePartial",
LoadingElementId = "progress2"
}))
{
<div id = "returnedquestion">
#Html.ValidationSummary(true)
<fieldset>
<legend>Answer here</legend>
<ol>
<li> <div class="editor-label">
#Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
#Html.TextBox("answer[0].Description")
#Html.ValidationMessageFor(model => model.Description)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.IsRight)
</div>
<div class="editor-field">
#Html.DropDownList("IsRight", String.Empty)
#Html.ValidationMessageFor(model => model.IsRight)
</div>
</li>
<li> <div class="editor-label">
#Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
#Html.TextBox("answer[1].Description")
#Html.ValidationMessageFor(model => model.Description)
</div> <div class="editor-label">
#Html.LabelFor(model => model.IsRight)
</div>
<div class="editor-field">
#Html.DropDownList("IsRight", String.Empty)
#Html.ValidationMessageFor(model => model.IsRight)
</div> </li>
<li> <div class="editor-label">
#Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
#Html.TextBox("answer[2].Description")
#Html.ValidationMessageFor(model => model.Description)
</div> <div class="editor-label">
#Html.LabelFor(model => model.IsRight)
</div>
<div class="editor-field">
#Html.DropDownList("IsRight", String.Empty)
#Html.ValidationMessageFor(model => model.IsRight)
</div> </li>
<li> <div class="editor-label">
#Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
#Html.TextBox("answer[3].Description")
#Html.ValidationMessageFor(model => model.Description)
</div> <div class="editor-label">
#Html.LabelFor(model => model.IsRight)
</div>
<div class="editor-field">
#Html.DropDownList("IsRight", String.Empty)
#Html.ValidationMessageFor(model => model.IsRight)
</div> </li>
<ol>
</fieldset>
<input type= "hidden" name = "questionid" value = #ViewBag.questionid>
<input type= "hidden" name = "assessmentid" value = #ViewBag.assessmentid>
<input type="submit" value="Add answer" />
</div>
}
</div>
and the following Post Ation Method:-
[HttpPost]
public ActionResult Create(int questionid, ICollection<Answer> answer)
{
if (ModelState.IsValid)
{
foreach (var a in answer){
repository.AddAnswer(a);
repository.Save();
}
return PartialView("_details2",answer);
}
return View("_details2",answer);}
and last thing the _details2 partial view which contains the newly added objects:-
#model IEnumerable<Elearning.Models.Answer>
#{
ViewBag.Title = "Details";
}
#foreach (var m in Model)
{
<tr id = #m.AnswersID>
<td>
#Html.DisplayFor(modelItem => m.Description)
</td>
<td>
#*#Html.DisplayFor(modelItem => Model.Answer_Description.description)*#
#ViewBag.Answerdesription
</td>
<td>
#Ajax.ActionLink("Delete", "Delete", "Answer",
new { id = m.AnswersID },
new AjaxOptions
{
Confirm = "Are You sure You want to delete this Answer ?",
HttpMethod = "Post",
UpdateTargetId = #m.AnswersID.ToString(),
OnSuccess = "removePartial2"
})
</td>
</tr>
}
but the above is not working nethier the objects will be added nor the partial view will be returned , so how i can solve this issue???
BR
You bind your view to a single Elearning.Models.Answer object, how are you expecting to get a collection of Answers as a parameter in your Action? The default model binder will try to bind your view fields to the parameter in the Action but it won't be able to as it's a collection.
What you could try to do is to bind your View to a List<Elearning.Models.Answer> and feed it 4 empty Answer objects, then you can create a strongly typed Partial view that expects one Elearning.Models.Answer, add the Partial in a foreach and, when posting the form, expect that the default model binder does it work and fill your action method with a brand new List of Answer objects.
As an alternative, you can create a View Model object that contains the fields in your View, including those 4 description fields. You add them as Html.TextboxFor to bind each of them to a different property in the View Model. Then you can collect them in your action, provided you change it to public ActionResult Create(int questionid, ViewModelAnswer answer)
Does it make sense?
Your model should contain a list and code like this:
#for (int i=0; i < Model.FavouriteMovies.Count; i++) {
#Html.LabelFor(model => model.YourList[i].Field)
#Html.EditorFor(model => model.YourList[i].Field)
#Html.ValidationMessageFor(model => model.YourList[i].Field)
}
which will print something like:
<label for="YourList_0__Field">Field Name</label>
The Field Name field is required.
And receive the model back in your controller:
public ActionResult MyAction(MyModel model)
{
// First element?
model.YourList[0].
}