Manage List of Image in Asp.Net MVC Page - javascript

I need to create an Asp.Net MVC 5 (Razor) view and controller capable to handle a list of Images.
Suppose a model like this one (the data are stored in a database and loaded with EF)
public class Game
{
public Guid Id {get; set; }
public string Title { get; set; }
public string ImageUrl {get; set; }
public ICollection<Screenshot> Screenshots { get; set; }
}
public class Screenshot
{
public Guid Id {get; set; }
public Game Game {get; set; }
public string Title {get; set; }
public string ImageUrl { get; set; }
}
I would like to:
1) create a page where the user can Create a Game and add one or more screenshots.
2) create a page where the user can Edit a Game info and add/remove any of screenshots.
Do you have any suggestion or example ?
Thanks

-To Add 1 or more screenshots, you might require using Ajax.BeginForm(...){}
-You might need an ability to add multiple images,[use ICollection to get save multiple images, after save, return the saved image data using the onSucccess event.
-For Editing, use the same logic, have a remove button on each image using ajax, then on success, remove image from screen.
Use same logic for adding new screenshots.
Using Ajax will also allow you to easier create effect for adding/ deleting images.
You can save images as I explained above to the db or even to a local temp folder that will be removed when the user clicks a save button, ect

Related

Pass collection of objects inside an object from js to C#

This question can be very easy for you but I cannot find the solution anywhere, I've searched on SO as well. How can I send a collection of objects inside an object to a C# API method, here is my code that I try to send
{
"Question":"sdvsdv",
"PollQuestions":
[
{
"QuestionText":"Question Text"
}
]
}
I've tried with Advanced REST client as well (not only from JS), I can see value of parent object's parameters but PollQuestions objects parameters are all empty.
Please suggest a work around. Its been couple of days and I cannot get through it. Thanks in advance.
EDIT:
Here is how API method looks like:
Advanced Rest client request:
JS request:
Poll is a simple class like this:
[Serializable]
[DataContract(Namespace = "")]
public class Poll
{
[DataMember]
public string Question
{
get;
set;
}
[DataMember]
public Collection<PollQuestion> PollQuestions { get; set; }
}
PollQuestion object:
[Serializable]
public class PollQuestion : AnotherClass
{
public string QuestionText
{
get;
set;
}
}
In your case if the problem is to Map the request JSON in C# then try below code:
Class structure:
public class PollQuestion
{
public string QuestionText { get; set; }
}
public class RootObject
{
public string Question { get; set; }
public List<PollQuestion> PollQuestions { get; set; }
}
In Post use [FromBody] attribute to map JSON to C# class:
public void YourMethod([FromBody] RootObject data)
{
// your code to use request data
}
If you are using WebAPI version="5.2.3" (Or might be supported in the lower version also) no need to serialize requested JSON to C# class. Use this to generate C# classes for JSON.
For JSON structure C# treats,
this:
{
}
as Object and
this:
[]
to List<> OR Array.
I set up a simple sample project in .NET Core and it seems to be working fine for me with your JSON data.
These are the classes I used:
public class PollQuestion
{
public string QuestionText { get; set; }
}
public class Poll
{
public string Question { get; set; }
public List<PollQuestion> PollQuestions { get; set; }
}
And here is the API call function:
[HttpPost]
public void Post([FromBody]Poll value)
{
}
When I make a postman request the Poll class is filled as expected.
Here is also a link to my sample project: https://bitbucket.org/alleskapaul/ld42/downloads/JsonExample.zip
Could you change your models in your project to match mine and see if that works? My guess would be that your model is incorrect as the JSON request works for me as well. If it is not working could you upload a sample project so I can see if I can modify it to work?
I was inheriting a class that was using [DataContract] and [DataMember] attributes, so I had to use DataMember for all parameters of the child class as well.
Thanks everyone for your answers but [FromBody] is not required in an API method when parameter is of complex type.
It works without DataContract and DataMember as well if you have not used DataMember anywhere in the class and also not inheriting any class that uses it.
You can get more info here: When to use DataContract and DataMember attributes?

Serialize form to string and deserealize it later to complex view model

I'm implementing the "Save Draft" functionality on my dynamically generated page and trying to make it as generic as possible. All my controllers and pages should support it and that's why I thought about creating a SaveDraft() POST action in my base controller which will receive a serialized form as a string which can be directly saved into the database and deserialized to a view model later in the specific get action using specific view model
[HttpPost]
public ActionResult SaveDraft(string jsonData, long id)
My first idea was to create the generic base controller and pass the view model type to it but the problem is that some controllers have multiple differently named POST actions and using different view model types, I cant change it now.
Some view models are complex and looking like
public class CollateralsDataModel
{
//...
public List<Applicant> Applicants { get; set; }
}
public class Applicant
{
public long ApplicantId { get; set; }
public IList<RealEstateSecurityCollateralsDTO> RealEstateSecurityCollaterals { get; set; }
public IList<AdditionalCollateralDTO> AdditionalCollaterals { get; set; }
}
public class RealEstateSecurityCollateralsDTO
{
[Required]
[Display(ResourceType = typeof(CollateralsData), Name = nameof(CollateralsData.RealEstateSecurityType))]
public int? RealEstateSecurityTypeId { get; set; }
//...
}
The input names on the form are looking like
"Applicants[0].MortgageApplicantId": "11595",
"Applicants[0].RealEstateSecurityCollaterals[0].Id": "17",
"Applicants[1].MortgageApplicantId": "11596",
"Applicants[1].RealEstateSecurityCollaterals.Index": "0",
"Applicants[1].AdditionalCollaterals[0].Id": "138",
"Applicants[1].AdditionalCollaterals[0].AdditionalCollateralTypeId": "4",
My question is - how can I serialize them to the string so I can deserialize it later?
I tried using different combinations of
$('.draft-data-form').serializeArray()
$('.draft-data-form').serialize()
JSON.stringify($('.draft-data-form').serializeArray());
but in my Action I get the flat JSON structure and I can't deserialize it
var obj = JsonConvert.DeserializeObject<CollateralsDataModel>(jsonData);
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type '...CollateralsDataModel' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
I've also tried to deserialize it as a list but then I get the List of 115 entries
var obj = JsonConvert.DeserializeObject<List<CollateralsDataModel>>(jsonData);
So my question is - how can I serialize them to the string so I can deserialize it later?
You do not want to serialize/deserialize a List. Only a single instance of the model.
I would guess that the error is in instantiating the list within the model. I know that the DataContractSerializer has an issue where if the List is not instantiated to an empty list when the model is constructed then the deserialization is unable to add to it.
Not sure if this is the same problem you are facing but could be worth a try.
eg. use:
public List<Applicant> Applicants { get; set; } = new List<Applicant>();

SignalR: exclude non serializable types

I have a class like this:
public class MyData
{
public int Id { get; set; }
public String Name { get; set; }
public ThirdPartyClass { get; set; } // non serializable
}
I said "non-serializable" because when I pass my class to a SignalR client function in this way:
var hub = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
var myData = new MyData();
// fill fields
hub.Clients.All.data(myData);
the call return error 500.
Removing the offending field it work as expected.
Please, note I'm not interested to pass to the client that field.
Right now I know two ways to solve this:
write a custom json serializer
create a shadow class with only the relevant fields, copy the values, and send this class to the clients
Both are uncomfortable when you have dozen of fields.
I'm wondering if there's some DataAnnotation I might use to exclude a field from serialization.
You can use IgnoreDataMemberAttribute() but I'm not sure if that would work with SignalR.
Your alternative if that doesn't work is the JsonIgnore annotation.
Lastly, there is also ScriptIgnore.
IgnoreDataMember Class Reference

How do I filter the Model based on the value of a textbox using Javascript (Razor)

this question may be totally non-sense but I am new in MVC and Razor.
Here is what I am trying to do:
I have a simple table "Products" from where I retrrieve all the
values using my model. The products table has a field Id, Name,
Price and StartDate.
I am passing the data from the Controller to
the view as a List
In the view I have an AutoComplete field (KendoUI) where I type the
name of the product
In the event handler
of the AutoCoplete change event, I want to retrieve the "Price" of
the product that has been typed in the AutoComplete textbox
Below is the code for the Product:
public class Product
{
public int ID { get; set; }
public string Name { get; set; }
public DateTime FirstRelease { get; set; }
public decimal Price { get; set; }
}
public class WidgetsDBContext : DbContext
{
public DbSet<Product> Products { get; set; }
}
The code for my View (partial code) is below:
<div id="auto">
<p>Start typing</p>
<label for="productAutoComplete">Please select procuct:</label>
#(Html.Kendo().AutoComplete()
.Name("productAutoComplete")
.DataTextField("Name")
.BindTo(Model)
.Filter(FilterType.StartsWith)
.Placeholder("Select the product")
.HighlightFirst(true)
.Suggest(true)
)
<script>
function productAutoComplete_change() {
var gauge = $("#linearGauge").data("kendoLinearGauge");
#foreach (var p in Model) <==== HERE I WANT TO DO THE FILTERING
{
#: gauge.value(#p.Price);
}
}
$("#productAutoComplete").bind("change", productAutoComplete_change);
</script>
</div>
CONCERN FOR VALIDATION: If I understand the basics of MVC and Razor well, then am I correct to think that the view is rendered once (during the HTTP GET) and therefore I am not able to dynamically filter the Model in Razor (but only in Javascript)? If yes, then what is the right way to do it?
Thank you in advance
Lefteris
am I correct to think that the view is rendered once (during the HTTP
GET) and therefore I am not able to dynamically filter the Model in
Razor (but only in Javascript)?
Yes, that's correct.
If yes, then what is the right way to do it?
You could use AJAX. For example in the productAutoComplete_change function you could send an AJAX request to a controller action that will perform the filtering and return a partial view containing the filtered results.
There are many tutorials out there about using AJAX with ASP.NET MVC. For example with jQuery you could use the $.ajax() function.

How to preserve a C# list in my view page, to manipulate that in client side

I m using ASP.Net MVC 3.0. My model has a list of telephone. I want to preserve that in some way, so that I can manipulate & display later using Jquery in my script.
I tried saving the list in a hidden field, but I am not able to retrieve that in my JavaScript.
Please help me finding a way out. Thx in advance.
You could create a property on your viewmodel which holds a json serialized version of the phonenumbers like this:
public class Person
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public IList<string> PhoneNumbers { get; set; }
public IHtmlString SerializedPhoneNumbers
{
get { return MvcHtmlString.Create(new JavaScriptSerializer().Serialize(PhoneNumbers)); }
}
}
You can use that in the view like:
<script type="text/javascript">
var phoneNumbers = #Model.SerializedPhoneNumbers
</script>
You now can manipulate the collection in your clientside script.

Categories

Resources