0

I have the following model class:

public class ItemClass
{
    public int TMSServerID {get;set;}
    public byte[] Timestamp {get;set;}
}

and inside my razor view i wrote the following, to display a checkbox that have its value as the objectid + timestamp:

<input type="checkbox" class="checkBoxClass" name="CheckBoxSelection" 
                               value="@(item.TMSServerID.ToString() + "~" + item.timestamp.ToString())"
                                /> 

but when I check the page source for my IE browser, I found the following:

<input type="checkbox" class="checkBoxClass" name="CheckBoxSelection" value="243~System.Byte[]"
                                /> 

so it seems that Razor view did not concatenate the timestamp value, and instead it concatenate the timestamp type which is byte[] ?

Edit

Now I have the following jquery which will capture the concatenated string and send it ot the action method:

var boxData = [];

        $("input[name='CheckBoxSelection']:checked").each(function () {
            boxData.push($(this).val());
        });

    }

         $.ajax({
             type: "POST",
             url: URL,
             data: { ids: boxData.join(",")}
            //code goes here

and action method is:

public ActionResult TransferSelectedServers(string ids, int? rackTo)
{

    if (ModelState.IsValid)
    {
        try
        {
            var serverIDs = ids.Split(',');
            int i = 0;
            foreach (var serverinfo in serverIDs)
            {
                var split = serverinfo.Split('~');

                var name = split[0];
                //System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();

                byte[] bytearray = Encoding.Default.GetBytes(split[1]);
                i++;
                var server = repository.FindServer_JTechnology(Int32.Parse(name));
                if (server == null)
                    return Json(new { IsSuccess = false, reload = true, description = " Some Servers might have been deleted, Transferre process has been cancelled .", rackid = rackFrom }, JsonRequestBehavior.AllowGet);

                server.RackID = rackTo;

                string ADusername = User.Identity.Name.Substring(User.Identity.Name.IndexOf("\\") + 1);
                repository.InsertOrUpdateServer(server, ADusername, server.Technology.IT360ID.Value, server.IT360SiteID, new bool(), server.Technology,bytearray);
            }

            repository.Save();


            return Json(new { IsSuccess = true, description = i + " Server/s Transferred Successfully To Rack " + }, JsonRequestBehavior.AllowGet);
        }
           catch (DbUpdateConcurrencyException e)
        {
            return Json(new { IsSuccess = false, reload = true, description = "records has been modified by another user" }, JsonRequestBehavior.AllowGet);


        }
        catch (Exception e)
        {
            return Json(new { IsSuccess = false, reload = true, description = " Server/s Can not Be Transferred to the Selected Rack "  }, JsonRequestBehavior.AllowGet);


        }
    }
    return RedirectToAction("Details", new { id = rackTo });

and the repository method is :-

public void InsertOrUpdateServer(TMSServer server, string username, long assetid, long? siteid = 0, bool isTDMHW = false, Technology t = null,byte[] timestamparray)
        {

                server.IT360SiteID = siteid.Value;
                tms.Entry(server).Property(s => s.timestamp).OriginalValue = timestamparray;
                tms.Entry(server).State = EntityState.Modified;
                var technology = tms.Technologies.Single(a => a.TechnologyID == server.TMSServerID);
                technology.IsManaged = t.IsManaged;
                tms.Entry(technology).State = EntityState.Modified;
                InsertOrUpdateTechnologyAudit(auditinfo);

            }

But currently I always get the following exception, even when I try editing the object by one user at a time:

Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries

    }
Cœur
  • 37,241
  • 25
  • 195
  • 267
John John
  • 1
  • 72
  • 238
  • 501

1 Answers1

1

Try

.... + Convert.ToBase64String(item.timestamp as byte[])"

Note this is how its done in the MVC Source Code for HiddenInput

and to convert the value back to Timestamp in the controller, use

byte[] timeStamp = Convert.FromBase64String(yourValue)
  • thanks this will render the correct timestamp inside my view, but inside my action method i wrote the following " byte[] bytearray = Encoding.Default.GetBytes(split[1]);" to extract the timestamp from the concatenated string. But the problem is that currently the timestamp extracted will not be the same as the tiemstamp rendered using "Convert.ToBase64String(item.timestamp as byte[])". although they shouldbe the same .. – John John Jul 31 '14 at 10:30
  • as i am doing two splits one to split the serverID+Timestamp combinations, while the second split to extract objectid and the timestsmp. – John John Jul 31 '14 at 10:42
  • 1
    I see (to separate the ID and Timestamp). Not sure why you would not just render hidden inputs for the ID and Timestamp separately to save all this extra code, but `Convert.FromBase64String()` method will 'reverse' the `Convert.ToBase64String()` output –  Jul 31 '14 at 10:43
  • well if i have seperate hidden fields then i can not know which id related to which timestamp,, as i am posting the data to the action method using jquery and not using model binder... – John John Jul 31 '14 at 10:48
  • so i am not sure if Encoding.Default.GetBytes(string) , will return exactly the byte[] that have been converted using Convert.FromBase64String(byte[])? – John John Jul 31 '14 at 10:51
  • Don't know enough about you app, but my approach would be to render separate values for `ID` and `Timestamp` along with a `checkbox` inside a `div`, then for each checked `checkbox`, get the corresponding values, construct array of javascript objects (that have properties matching `class ItemClass`) and post back via AJAX to `ActionResult TransferSelectedServers(IEnumerable items)` –  Jul 31 '14 at 10:57
  • i avoid doing so as i do not need any of the object properties, since my action method will just update the rackid for the selected servers.. – John John Jul 31 '14 at 11:04
  • Well you need `int TMSServerID` and `byte[] Timestamp` and they are the only 2 properties you have shown in `ItemClass`. And if there are others you excluded, you could use another model - buts that's just my approach - if yours works, stick with it :) –  Jul 31 '14 at 11:09
  • basically the ItemClass contians many other properties, but using jquery i can not post the model objects same as i do id i am posting using model binder... – John John Jul 31 '14 at 11:39
  • and even if my approach is not the best , but it should work , as i am converting byte[] to a sting, post the string to the action method, convert the string to a byte[] do the update. so if the records was not modified by another user,, the update should work , since the timestamp posted by the jQuery should match the one inside the update statement ,, – John John Jul 31 '14 at 11:41
  • If you used `ActionResult TransferSelectedServers(IEnumerable items)` where `class DeleteItemClass` contains just the `ID` and `Timestamp` properties, and you format the JSON correctly, (like `[{TMSServerID: ???, Timestamp: ???}, {...}]`) the `DefaultModelBinder` will do all the work for you –  Jul 31 '14 at 11:45
  • but can you advice where i need to format the JSON, as currently i am capturing the values of the checkboxes using jquery and post it to the action method.. – John John Jul 31 '14 at 12:46
  • Have a look at the [answer to this question](http://stackoverflow.com/questions/2250953/how-do-i-create-javascript-arrayjson-format-dynamically). to see how to construct array of objects. Add one object for each checked checkbox, then in the AJAX call, `data: JSON.stringify(yourArray)` - note property names must match your model properties –  Jul 31 '14 at 13:03
  • i will look into your approach , but for now using Convert.FromBase64String(yourValue) have solved ym issue – John John Jul 31 '14 at 16:35